const char* BUILT_IN_DEBUG =
	"/*\n"
	"\tdebug.pika v0.941\n"
	"\n"
	"\tPikaScript is released under the \"New Simplified BSD License\". http://www.opensource.org/licenses/bsd-license.php\n"
	"\t\n"
	"\tCopyright (c) 2009-2013, NuEdge Development / Magnus Lidstroem\n"
	"\tAll rights reserved.\n"
	"*/\n"
	"\n"
	"include('stdlib.pika');\n"
	"\n"
	"CONSOLE_COLS = 120;\n"
	"CONSOLE_ROWS = 30;\n"
	"\n"
	"assert = function {\n"
	"\tif (!(if (classify($0) === 'function') $0() else $0)) throw('Assertion failure: ' # coalesce(@$1, @$0));\n"
	"\t( void )\n"
	"};\n"
	"\n"
	"limitLength = function { if (length($0) <= $1) ( $0 ) else ( $0{:$1 - 3} # '...' ) };\n"
	"singleLine = function { replace($0, \"\\t\\r\\n\", ' ', find, 1) };\n"
	"\n"
	"// FIX : use \"more\" (or implement same functionality here)...\n"
	"dump = function {\n"
	"\tvargs(, @var); defaults(@var, @^);\n"
	"\tprint('Dumping ' # var # ' of ' # describeCall(var) # LF # repeat('=', 8));\n"
	"\tif (exists(var)) print(var # ' = ' # limitLength(singleLine(toSource([var])), CONSOLE_COLS - length(var) - 3));\n"
	"\tforeach(var, >print($1 # ' = ' # limitLength(singleLine(toSource($2)), CONSOLE_COLS - length($1) - 3)));\n"
	"\t( void )\n"
	"};\n"
	"\n"
	"// FIX : shouldn't be required... we should build the \"more\" facility into interactive.pika.\n"
	"more = function {\n"
	"\targs(@s);\n"
	"\tlineOut => if (!silent) {\n"
	"\t\tprint($0);\n"
	"\t\tif (++lc >= CONSOLE_ROWS) {\n"
	"\t\t\tlc = 0;\n"
	"\t\t\tif (lower(input(\"---- more (yes)? \")){0} === 'n') silent = true;\n"
	"\t\t}\n"
	"\t};\n"
	"\tlc = 0;\n"
	"\tsilent = false;\n"
	"\ttokenize(s, >if (!silent) lineOut($0));\n"
	"\t( void )\n"
	"};\n"
	"\n"
	"// FIX : overlaps with dump, and I don't like the name, too generic\n"
	"//show = function {\n"
	"//\targs(@var);\n"
	"//\tmore(var # if (classify(var) === 'reference' && (s = sourceFor(var, ' ')) !== '')\n"
	"//\t\t\t(LF # repeat('=', 8) # LF # s # repeat('=', 8)));\n"
	"//\t( void )\n"
	"//};\n"
	"\n"
	"describeCall = function {\n"
	"\ts = (if (exists(@[$0].$callee)) [$0].$callee else '(unknown)') # '(';\n"
	"\tif (exists(@[$0].$n)) {\n"
	"\t\tfor (i = 0; i < [$0].$n; ++i) {\n"
	"\t\t\tif (exists(@[$0].$[i])) s #= limitLength(singleLine(toSource([$0].$[i])), CONSOLE_COLS);\n"
	"\t\t\tif (i < [$0].$n - 1) s #= ', '\n"
	"\t\t}\n"
	"\t};\n"
	"\ts #= ')';\n"
	"\t( s )\n"
	"};\n"
	"\n"
	"callstack = function {\n"
	"\tvargs(, @frame, @prefix); defaults(@frame, @^, @prefix, '');\n"
	"\tfor (; { print(prefix # describeCall(frame)); frame !== '::'; }; frame = @[frame # '^']) ;\n"
	"\t( void )\n"
	"};\n"
	"\n"
	"NO_TRACE_LEVEL = 0;\n"
	"ERROR_TRACE_LEVEL = 1;\n"
	"CALL_TRACE_LEVEL = 2;\n"
	"LOOP_TRACE_LEVEL = 3;\n"
	"STATEMENT_TRACE_LEVEL = 4;\n"
	"BODY_TRACE_LEVEL = 5;\n"
	"ARGUMENT_TRACE_LEVEL = 6;\n"
	"BRACKET_TRACE_LEVEL = 7;\n"
	"MAX_TRACE_LEVEL = 22;\n"
	"\n"
	"traceVerbose = function {\n"
	"\ttrace(function {\n"
	"\t\tif (!exists(@^$callee) || !exists(@::traceVerbose.filter[^$callee])) {\n"
	"\t\t\targs(@source, @offset, @lvalue, @result, @level, @exit);\n"
	"\t\t\tif (level == CALL_TRACE_LEVEL) {\n"
	"\t\t\t\t\t\t// FIX : subroutine\n"
	"\t\t\t\tif (exists(@^$callee)) source = ^$callee;\n"
	"\t\t\t\ts = (if (exit) '}-- ' else '--{ ') # describeCall(@^);\n"
	"\t\t\t\tif (exit) s #= ' = ' # limitLength(singleLine(toSource(result)), CONSOLE_COLS \\ 4);\n"
	"\t\t\t} else {\n"
	"\t\t\t// FIX : use repeat\n"
	"\t\t\t\tfixedWidth = function { $0 = $0{:$1}; for (; length($0) < $1; $0 #= ' ') ; $0 };\n"
	"\t\t\t\ts = ' ' # fixedWidth(singleLine(source{offset - 4:4}), 4) # ' <> ' # fixedWidth(singleLine(source{offset:}), CONSOLE_COLS \\ 4)\n"
	"\t\t\t\t\t\t# ' | (' # (if (exit) '<' else '>') # level # ') ' # (if (lvalue) result else limitLength(singleLine(toSource(result)), CONSOLE_COLS \\ 4));\n"
	"\t\t\t};\n"
	"\t\t\tprint(s);\n"
	"\t\t}\n"
	"\t}, coalesce(@$0, CALL_TRACE_LEVEL));\n"
	"\t( void )\n"
	"};\n"
	"\n"
	"traceCalls = function {\n"
	"\t::traceCalls.depth = 0;\n"
	"\t::traceCalls.filter['args'] = true;\n"
	"\t::traceCalls.filter['vargs'] = true;\n"
	"\t::traceCalls.filter['defaults'] = true;\n"
	"\ttrace(function {\n"
	"\t\tif (!exists(@^$callee) || !exists(@::traceCalls.filter[^$callee])) {\n"
	"\t\t\targs(@source, @offset, @lvalue, @result, @level, @exit);\n"
	"\t\t\tif (level == ERROR_TRACE_LEVEL) print(' !!!! ' # result);\n"
	"\t\t\tif (level == CALL_TRACE_LEVEL) {\n"
	"\t\t\t\ts = describeCall(@^);\n"
	"\t\t\t\tif (!exit) ++::traceCalls.depth\n"
	"\t\t\t\telse {\n"
	"\t\t\t\t\ts #= ' = ' # limitLength(singleLine(toSource(result)), CONSOLE_COLS \\ 4);\n"
	"\t\t\t\t\t--::traceCalls.depth;\n"
	"\t\t\t\t};\n"
	"\t\t\t\tprint(repeat(' ', traceCalls.depth) # s);\n"
	"\t\t\t}\n"
	"\t\t}\n"
	"\t}, CALL_TRACE_LEVEL);\n"
	"\t( void )\n"
	"};\n"
	"\n"
	"debug.tracer = function {\n"
	"// TODO : slimline\n"
	"\targs(@source, @offset, @lvalue, @result, @level, @exit);\n"
	"\tleave = false;\n"
	"\tif (level == ERROR_TRACE_LEVEL) {\n"
	"\t\texit = false; // for the error level, exit just indicates that it is the last catch in the chain\n"
	"\t\tprint(' !!!! ' # result);\n"
	"\t\t::debug.callDepth = 0;\n"
	"\t};\n"
	"\tif (exit) {\n"
	"\t\tif (level == CALL_TRACE_LEVEL) --::debug.callDepth;\n"
	"\t\tif (debug.callDepth <= 0) {\n"
	"\t\t\tif (!::debug.lastWasExit) print(' (' # (if (lvalue) result else replace(limitLength(toSource(result), CONSOLE_COLS \\ 4), \"\\n\", ' ')) # ')');\n"
	"\t\t\tif (debug.callDepth < 0 && level == CALL_TRACE_LEVEL) print(' <<<<');\n"
	"\t\t}\n"
	"\t} else {\n"
	"\t\tif (level == CALL_TRACE_LEVEL) ++::debug.callDepth;\n"
	"\t\tif (debug.callDepth <= 0) {\n"
	"\t\t\thelp = \"enter   step over\\n    >   step in\\n    <   step out\\n    ^   continue\\n    !   stop\\n    =   dump locals\\n    :   dump globals\\n    (   call-stack\\n    {   show function\\n\\nanything else evaluates expression\\n\";\n"
	"\t\t\tprompt = replace(source{offset:81}, \"\\t\", ' ');\n"
	"\t\t\tprompt = limitLength(prompt{:find(prompt, \"\\n\")}, CONSOLE_COLS);\n"
	"\t\t\tif (level != CALL_TRACE_LEVEL) prompt = ' >>>> ' # prompt\n"
	"\t\t\telse prompt = ' ===> ' # describeCall(@^);\n"
	"\t\t\tfor (; {\n"
	"\t\t\t\t\tprint(prompt);\n"
	"\t\t\t\t\ts = input('debug> ');\n"
	"\t\t\t\t\tif (s === '^') { leave = true; false; }\n"
	"\t\t\t\t\telse if (s === '<') { ::debug.callDepth = 1; false; }\n"
	"\t\t\t\t\telse if (s === '>') { ::debug.callDepth = -1; false; }\n"
	"\t\t\t\t\telse if (s === '') { ::debug.callDepth = 0; false; }\n"
	"\t\t\t\t\telse true;\n"
	"\t\t\t\t} ; ) {\n"
	"\t\t\t\tif (s === '?') print(help)\n"
	"\t\t\t\telse if (s === '!') throw('Debugger stop')\n"
	"\t\t\t\telse if (s === '=') dump(@^) // FIX : also list non-closure @^$ in case closure frame differs from $ frame\n"
	"\t\t\t\telse if (s === ':') dump(@::)\n"
	"\t\t\t\telse if (s === '{') print(source{:offset} # ' <####> ' # source{offset:}) // FIX : display func name first\n"
	"\t\t\t\telse if (s === '(') callstack(@^)\n"
	"\t\t\t\telse {\n"
	"\t\t\t\t\tx = try(>s = evaluate(s, @^^^$));\n"
	"\t\t\t\t\tprint(if (x !== void) x else s);\n"
	"\t\t\t\t}\n"
	"\t\t\t}\n"
	"\t\t}\n"
	"\t};\n"
	"\t::debug.lastWasExit = exit;\n"
	"\tif (leave) traceLevel = ERROR_TRACE_LEVEL\n"
	"\telse if (debug.callDepth > 0) traceLevel = CALL_TRACE_LEVEL\n"
	"\telse traceLevel = BODY_TRACE_LEVEL;\n"
	"\ttrace(debug.tracer, traceLevel);\n"
	"\t( void )\n"
	"};\n"
	"\n"
	"debug = function {\n"
	"\t::debug.lastWasExit = false;\n"
	"\tif (exists(@$0)) {\n"
	"\t\t::debug.callDepth = -1;\n"
	"\t\ttrace(debug.tracer, CALL_TRACE_LEVEL);\n"
	"\t\t$0();\n"
	"\t} else {\n"
	"\t\t::debug.callDepth = 1;\n"
	"\t\ttrace(debug.tracer, CALL_TRACE_LEVEL);\n"
	"\t\tprint('*** DEBUGGER BREAK ***');\n"
	"\t\t( void );\n"
	"\t}\n"
	"};\n"
	"\n"
	"traceErrors = function {\n"
	"\ttrace(function {\n"
	"\t\targs(@source, @offset, @lvalue, @result, @level, @exit);\n"
	"\t\tCC4 = CONSOLE_COLS \\ 4;\n"
	"\t\ts = singleLine(source{offset - CC4:CC4} # ' <!!!!> ' # source{offset:CC4});\n"
	"\t\tif (offset > CC4) s = '... ' # s;\n"
	"\t\tif (offset + CC4 < length(source)) s #= ' ...';\n"
	"\t\tprint('   ! ' # describeCall(@^) # ' !   ' # s);\n"
	"//\t\tif (exit) print('!!!! ' # result);\n"
	"\t\tif (exit) print('');\n"
	"\t}, ERROR_TRACE_LEVEL);\n"
	"};\n"
	"\n"
	"profile = function {\n"
	"\t::profiler.dump = function { dump(@::profiler.counters); };\n"
	"\t::profiler.reset = function { prune(@::profiler.counters); };\n"
	"\t::profiler.tick = function { \n"
	"\t\t::profiler.ticker = ::profiler.skip;\n"
	"\t\tif ((t = time()) != ::profiler.last) {\n"
	"\t\t\t::profiler.last = t;\n"
	"\t\t\tif (exists(f = @^^$callee)) {\n"
	"\t\t\t\tprint('');\n"
	"\t\t\t\tc = @::profiler.counters[[f]];\n"
	"\t\t\t\tdefaults(c, 0);\n"
	"\t\t\t\t[c]++;\n"
	"\t\t\t\tprint('   @ ' # [f] # ': ' # [c]);\n"
	"args(@source, @offset);\n"
	"CC4 = CONSOLE_COLS \\ 2 - 16 - 5;\n"
	"s = singleLine(source{offset - CC4:CC4} # ' <####> ' # source{offset:CC4});\n"
	"if (offset > CC4) s = '... ' # s;\n"
	"if (offset + CC4 < length(source)) s #= ' ...';\n"
	"print('     ' # s);\n"
	"\t\t\t\tcallstack(@^^, '     ');\n"
	"\t\t\t\tprint('');\n"
	"\t\t\t}\n"
	"\t\t}\n"
	"\t};\n"
	"\n"
	"\t::profiler.ticker = 0;\n"
	"\ttrace(function { ++::profiler.ticker; }, STATEMENT_TRACE_LEVEL);\n"
	"\tprint('Calibrating...');\n"
	"\tfor (t = time(); (t2 = time()) == t;);\n"
	"\tfor (::profiler.ticker = 0; time() == t2;) wildmatch(random(1), '[0-8.]*');\n"
	"\t::profiler.skip = (::profiler.ticker \\= 4);\n"
	"\tprint(\"Profiling started.\\n\\nprofiler.dump() show accumulated call counts.\\nprofiler.reset() resets call counts.\\ntrace() stops profiling.\");\n"
	"\t::profiler.last = time();\n"
	"\ttrace(function { if (--::profiler.ticker <= 0) profiler.tick($0, $1); }, STATEMENT_TRACE_LEVEL);\n"
	"\t( void )\n"
	"};\n"
	"\n"
	"clock = function {\n"
	"\targs(@func);\n"
	"\tprint('----- Clocking...');\n"
	"\tfor (t = time() + 1; time() < t;);\n"
	"\tipersec = { i = 0; for (++t; time() < t;) ++i; };\n"
	"\tfunc();\n"
	"\tj = 0; for (u = time() + 1; time() < u; ++j);\n"
	"\tprint('----- Clocked: ' # (u - t - min(j, ipersec) / ipersec) # ' secs');\n"
	"\t( void )\n"
	"};\n"
	"\n"
	"traceErrors();\n"
	"\n"
	"// Define dummy help that loads the help.pika on demand.\n"
	"help = function { /****    Type help() to get started.    ****/        run('help.pika'); invoke('help', , @$) };\n"
	"\n"
	"void;\n";

const char* BUILT_IN_HELP =
	"/*\n"
	"\thelp.pika v0.941\n"
	"\n"
	"\tPikaScript is released under the \"New Simplified BSD License\". http://www.opensource.org/licenses/bsd-license.php\n"
	"\t\n"
	"\tCopyright (c) 2009-2013, NuEdge Development / Magnus Lidstroem\n"
	"\tAll rights reserved.\n"
	"*/\n"
	"\n"
	"include('stdlib.pika');\n"
	"\n"
	"prune(@help);\n"
	"\n"
	"describe = function {\n"
	"\tvargs(@category, @page, @syntax,, @description, @examples, @seealso);\n"
	"\tif (exists(@::help[page])) throw('Help page ' # escape(page) # ' already described');\n"
	"\t::help._categories[category][page] = page;\n"
	"\t::help[page].category = category;\n"
	"\t::help[page].syntax = syntax;\n"
	"\t::help[page].description = coalesce(@description);\n"
	"\t::help[page].examples = coalesce(@examples);\n"
	"\t::help[page].seealso = coalesce(@seealso);\n"
	"\tfull = 'SYNTAX' # LF # syntax # LF # LF # 'CATEGORY' # LF # category;\n"
	"\tif (exists(@description)) full #= LF # LF # 'DESCRIPTION' # LF # description;\n"
	"\tif (exists(@examples)) full #= LF # LF # 'EXAMPLE(S)' # LF # examples;\n"
	"\tif (exists(@seealso)) full #= LF # LF # 'SEE ALSO' # LF # seealso;\n"
	"\t::help[page] = full;\n"
	"\t::help._isdirty = true;\n"
	"};\n"
	"\n"
	"help._isdirty = false;\n"
	"help._lookup = function {\n"
	"\tif (help._isdirty) {\n"
	"\t\t::help._isdirty = false;\n"
	"\t\t::help['#categories'] = 'Defined help categories:' # LF # LF;\n"
	"\t\tlastCategory = '';\n"
	"\t\tforeach(@::help._categories, >{\n"
	"\t\t\ti = find($1, '.');\n"
	"\t\t\tthisPage = $1{(i + 1):};\n"
	"\t\t\tthisCategory = $1{:i};\n"
	"\t\t\tif (lastCategory !== thisCategory) {\n"
	"\t\t\t\tif (lastCategory !== '') ::help[lastCategory] = pageList{:length(pageList) - 2};\n"
	"\t\t\t\tlastCategory = thisCategory;\n"
	"\t\t\t\tpageList = 'The category ' # thisCategory # ' contains the following help pages:' # LF # LF;\n"
	"\t\t\t\t::help['#categories'] #= thisCategory # ', ';\n"
	"\t\t\t};\n"
	"\t\t\tpageList #= thisPage # ', ';\n"
	"\t\t});\n"
	"\t\tif (lastCategory !== '') ::help[lastCategory] = pageList{:length(pageList) - 2};\n"
	"\t\t::help['#pages'] = 'Available help pages:' # LF # LF;\n"
	"\t\tforeach(@::help, >if ($1{0} !== '_' && find('.', $1) != 0) ::help['#pages'] #= $1 # ', ');\n"
	"\t\t::help['#categories'] = ::help['#categories']{:length(::help['#categories']) - 2};\n"
	"\t\t::help['#pages'] = ::help['#pages']{:length(::help['#pages']) - 2};\n"
	"\t};\n"
	"\tpage = coalesce(@$0, 'help');\n"
	"\tif (page{0} === '/') {\n"
	"\t\tsearchFor = lower(page{1:});\n"
	"\t\tsearchLen = length(searchFor);\n"
	"\t\tsurroundChars = max(30 - (searchLen >> 1), 10);\n"
	"\t\tfound = 0;\n"
	"\t\tforeach(@::help, >{\n"
	"\t\t\tif ($1{0} !== '_' && find('.', $1) != 0 && (i = search(lower($2), searchFor)) < length($2)) {\n"
	"\t\t\t\t$line = $2{i - surroundChars:surroundChars} # '--->' # $2{i:searchLen}\n"
	"\t\t\t\t\t\t# '<---' # $2{i + searchLen:surroundChars};\n"
	"\t\t\t\tif (found == 0) print(\"The following pages contains the search string (showing only the first match for each page):\\n\");\n"
	"\t\t\t\tprint($1 # repeat(' ', 12 - length($1)) # ':  ' # replace($line, \"\\t\\n\", ' ', find, 1));\n"
	"\t\t\t\t++found;\n"
	"\t\t\t}\n"
	"\t\t});\n"
	"\t\tif (found == 0) print(\"No page contained the search string\");\n"
	"\t} else if (exists(@::help[page])) print(repeat('=', 20) # LF # help[page] # LF # repeat('=', 20))\n"
	"\telse print('No help page called ' # escape(page) # \". Type help('#pages') to list all available pages.\");\n"
	"\t( void )\n"
	"};\n"
	"\n"
	"help = function { /****    Type help() to get started.    ****/        invoke('help._lookup', , @$) };\n"
	"\t\n"
	"describe('#containers', 'ascend',\t\"@parent = ascend(@child)\",\t\t\t\t\t\t\"Returns a reference to the \\\"parent container\\\" of @child (i.e. the variable or element that contains the sub-element referred to by @child). If @child is a top-level variable, void is returned.\", \"ascend(@x['3']) === @x\\nascend(@x.y.z) === @x.y\\nascend(@x) === void\");\n"
	"describe('#containers', 'clone',\t\"@target = clone(@source, @target)\",\t\t\t\"Makes a \\\"deep copy\\\" of the container @source to @target, meaning that all elements under the source and any sub-elements that they may have (and so on) will be copied to the target. If there is a variable directly at @source it will also be copied to @target. The returned value is the input @target reference.\\n\\nNotice that this function does not erase any existing elements under @target. You may want to consider calling prune() on @target first.\", \"clone(@originalData, @myCarbonCopy)\", 'copy, prune');\n"
	"describe('#containers', 'foreach',\t\"foreach(@map, >doThis)\",\t\t\t\t\t\t\"Traverses all elements under @map (and any sub-elements that they may have and so on) and calls >doThis once for every encountered element. (An alternative description of foreach() is that it calls >doThis for every found variable that begins with the value of @map # '.') Three arguments will be passed to >doThis:\\n\\n$0 will be the full reference to the found element (e.g. \\\"::zoo.elephant\\\")\\n$1 will be the name of the element (e.g. \\\"elephant\\\")\\n$2 will be the value of the element.\\n\\nThe order with which elements are processed is undefined and depends on the implementation of PikaScript. Any modifications to @map while running foreach() will not be reflected in the calls to >doThis. Notice that you normally would not use foreach() on arrays since it would also include the 'n' element (the element count). Use iterate() or a simple for-loop instead.\", \"foreach(map(@a, 'Asia', 4157, 'Africa', 1030, 'Americas', 929, 'Europe', 739, 'Oceania', 35), >print($1 # '=' # $2))\", 'iterate');\n"
	"describe('#containers', 'map',\t\t\"@map = map(@map, ['keys', <values>, ...])\",\t\"Creates a \\\"map\\\" under @map by assigning sub-elements to @map for each key / value pair passed to the function. The returned value is the input @map reference.\\n\\nNotice that this function does not erase any existing elements under @map so you may call this function repeatedly to incrementally build a map. Use prune on @map to delete it.\\n\\nA creative use of this function is to create efficient \\\"switch statements\\\" something that is otherwise missing in PikaScript by mapping keys to functions / lambda expressions. You could then execute the switch like this: mySwitch[theKey].\", \"map(@userInfo['magnus'], 'fullName','Magnus Lidstroem' , 'birthDate','31 march 1972' , 'favoriteColor','#3333FF')\\nmap(@actions, 'hi',>print('Good day sir!') , 'spin',>{ for (i = 0; i < 360; ++i) print('Spun ' # i # ' degrees') } , 'quit',>doQuit = true)\\n[map(@temp, 'zero',0 , 'one',1 , 'two',2 , 'three',3)]['two'] == 2\", 'foreach, prune, set');\n"
	"describe('#containers', 'prune',\t\"+count = prune(@reference)\",\t\t\t\t\t\"Deletes the variable referenced to by @reference as well as all its sub-elements. Use prune() to delete an entire \\\"plain old data\\\" container (e.g. an \\\"array\\\" or \\\"map\\\"). Use destruct() instead for deleting an \\\"object\\\" to have its destructor called before it is deleted. prune() returns the number of variables that were deleted.\", \"prune(@myArray)\", 'delete, destruct');\n"
	"describe('#containers', 'redotify',\t\"'zzz...' = redotify('zzz%2e%2e%2e')\",\t\t\t\"Decodes an \\\"undotified\\\" string as returned from undotify(). See help for \\\"undotify\\\" for further explanation and examples.\", \"redotify('nearly 50%25 use google%2ecom daily') === 'nearly 50% use google.com daily'\", 'undotify');\n"
	"describe('#containers', 'set',\t\t\"@set = set(@set, ['keys', ...])\",\t\t\t\t\"Creates a \\\"set\\\" under @set by assigning sub-elements with the value true for each key. The returned value is the input @set reference.\\n\\nNotice that this function does not erase any existing elements under @set so you may call this function repeatedly to incrementally build a set. Use prune() on @set to delete it.\\n\\nOne practical use for sets is to efficiently check if a value belongs to a group of values. Initially you create the group of values with this function and later you can call exists(@set[key]).\", \"set(@validColors, 'red', 'green', 'blue', 'yellow')\\nexists(@[set(@smallPrimes, 2, 3, 5, 7, 11, 13, 17, 19)][13])\", 'foreach, map, prune');\n"
	"describe('#containers', 'undotify',\t\"'zzz%2e%2e%2e' = undotify('zzz...')\",\t\t\t\"Simply replaces all '.' with '%2e' and all '%' with '%25'. The purpose of this function is to allow arbitrary strings to work as keys in multi-dimensional arrays / deep containers. Without \\\"undotifying\\\" keys, any '.' in the keys would be interpreted as separators. E.g. \\\"files['name.ext'].size\\\" is the same as \\\"files.name.ext.size\\\", which is probably not what you want. Instead use \\\"files[undotify('name.ext')].size\\\". To return the original key from an \\\"undotified\\\" key, use redotify().\", \"undotify('nearly 50% use google.com daily') === 'nearly 50%25 use google%2ecom daily'\\nredotify(undotify('a.b.c%d.e.f')) === 'a.b.c%d.e.f'\", 'redotify');\n"
	"\n"
	"describe('#arrays', 'append',\t\"@array = append(@array, [<elements>, ...])\",\t\t\"Appends <elements> to @array. If [@array].n does not exist it will be initialized to 0 and this routine will in practice work like compose(). Unlike compose() however, all element argument must be present. The returned value is the input @array reference.\\n\\nNotice that calling this function on a \\\"double-ended queue\\\" also works.\", \"append(@myArray, 5, 6, 7, 8)\\nequal(append(compose(@temp1, 'a', 'b', 'c'), 'd', 'e', 'f'), compose(@temp2, 'a', 'b', 'c', 'd', 'e', 'f')) == true\", 'compose, insert');\n"
	"describe('#arrays', 'compose',\t\"@array = compose(@array, [<elements>, ...])\",\t\t\"Creates an array of indexed elements under @array initialized with the values of the remaining arguments (<element>). The first element will have an index of zero (e.g. \\\"array[0]\\\"). The special element 'n' (e.g. \\\"array.n\\\") will contain the number of indexed elements in the array. If an element argument is omitted the corresponding element will not be initialized, possibly making the array \\\"non-contiguous\\\". The returned value is the input @array reference.\\n\\nNotice that this function does not erase any existing elements under @array. You may want to consider calling prune() on @array before composing a new array.\", \"compose(@myArray, 1, 2, 3, 4)\\ncompose(@holy, 'nextIsEmpty', , 'previousWasEmpty')\\n[compose(@temp, 'zero', 'one', 'two', 'three')][2] === 'two'\", 'append, decompose, map, prune');\n"
	"describe('#arrays', 'copy',\t\t\"@target = copy(@source, +offset, +count, @target, +index)\", \"Copies +count elements from the @source array beginning at +offset into @target at +index, replacing any already existing elements at the target indices. The element count of the @target array (i.e. [@target].n) may be incremented to fit the new elements.\\n\\nThe @source array must be contiguous. If the output +index is greater than [@target].n (or (+index) + (+count) < 0), the resulting array will become non-contiguous.\\n\\nOnly direct elements under the arrays will be affected. Any sub-elements that they in turn may have are ignored. @source and @target may reference the same array. The returned value is the input @target reference.\", \"copy(@myArray, 10, 5, @myArray, 13)\\nequal(copy(compose(@temp1, 'a', 'b', 'c', 'd'), 1, 2, compose(@temp2, 'e', 'f', 'g', 'h'), 3), compose(@temp3, 'e', 'f', 'g', 'b', 'c')) == true\", 'clone, inject, remove');\n"
	"describe('#arrays', 'decompose',\"decompose(@array, [@variables, ...])\",\t\t\t\t\"Decomposes an array by storing the indexed elements under @array one by one into the given references. If an argument is left empty, the corresponding element index will be skipped.\", \"decompose(@breakMe, @first, @second, @third, , @noFourthButFifth)\", 'compose');\n"
	"describe('#arrays', 'equal',\t\"?same = equal(@arrayA, @arrayB)\",\t\t\t\t\t\"Returns true if the arrays @arrayA and @arrayB are the same size and all their elements are identical. Both arrays must be contiguous (i.e. all their elements must be defined). Only direct elements under the arrays will be tested. Any sub-elements that they in turn may have are silently ignored.\", \"equal(@firstArray, @secondArray)\\nequal(compose(@temp1, 1, 10, 100, 'one thousand'), compose(@temp2, 1, 10, 100, 'one thousand')) == true\");\n"
	"describe('#arrays', 'fill',\t\t\"@array = fill(@array, +offset, +count, <value>)\",\t\"Fills a range of +count elements in @array with <value> starting at +offset, replacing any existing elements. If the target @array does not exist (i.e. [@array].n is not defined) it is created. The element count (i.e. [@array].n) may be incremented to fit the new elements.\\n\\nOnly direct elements under the arrays will be affected. The returned value is the input @array reference.\", \"equal(fill(@a, 0, 5, 'x'), compose(@b, 'x', 'x', 'x', 'x', 'x'))\", 'copy, inject, insert, remove');\n"
	"describe('#arrays', 'inject',\t\"@target = inject(@source, +offset, +count, @target, +index)\", \"Inserts +count elements from the @source array beginning at +offset into @target at +index, relocating any elements at and after +index to make room for the inserted elements. Both arrays must be contiguous and the target +index must be between 0 and [@target].n. Only direct elements under the arrays will be affected. Any sub-elements that they in turn may have are ignored. @source and @target should not reference the same array. The returned value is the input @target reference.\", \"inject(@myArray, 10, 5, @myArray, 13)\\nequal(inject(compose(@temp1, 'a', 'b', 'c', 'd'), 1, 2, compose(@temp2, 'e', 'f', 'g', 'h'), 3), compose(@temp3, 'e', 'f', 'g', 'b', 'c', 'h')) == true\", 'copy, fill, insert, remove');\n"
	"describe('#arrays', 'iterate',\t\"iterate(@array, >doThis)\",\t\t\t\t\t\t\t\"Iterates all elements in @array (as determined by [@array].n) and calls >doThis once for every encountered element in ascending index order. Three arguments will be passed to >doThis:\\n\\n$0 will be the full reference to the found element (e.g. \\\"::highscores.3\\\")\\n$1 will be the element index (e.g. 3)\\n$2 will be the value of the element.\\n\\niterate() is the equivalent to foreach() for arrays. Any change to [@array].n while running iterate() will not be accounted for. The array must be contiguous. Only direct elements under the array will be iterated.\", \"iterate(compose(@a, 0, 'one', 2, true), >print($1 # '=' # $2))\", 'foreach');\n"
	"describe('#arrays', 'insert',\t\"@array = insert(@array, +offset, [<elements>, ...])\",\t\"Inserts one or more elements into @array before the index +offset. The array must be contiguous. Only direct elements under the array will be moved to make room for the new elements. Any sub-elements that they in turn may have remain unaffected. +offset must be between 0 and the element count of @array (or an exception will be thrown). [@array].n must be defined prior to calling this routine. The returned value is the input @array reference.\", \"insert(@myArray, 10, 'insert', 'three', 'strings')\\nequal(insert(compose(@temp1, 'a', 'b', 'f'), 2, 'c', 'd', 'e'), compose(@temp2, 'a', 'b', 'c', 'd', 'e', 'f')) == true\", 'inject, remove');\n"
	"describe('#arrays', 'remove',\t\"@array = remove(@array, +offset, [+count = 1])\",\t\"Removes +count number of elements from @array beginning at +offset, relocating any elements after the removed elements so that the array remains contiguous. (Only direct elements under the array are moved. Any sub-elements under these elements will be left untouched.)\\n\\nIf +offset and / or +count are negative, this function still yields predictable results (e.g. an +offset of -3 and +count of 6 will remove the three first elements). Likewise, it is allowed to remove elements beyond the end of the array (but naturally it will have no effect). The returned value is the input @array reference.\", \"remove(@removeNumberThree, 3)\\nremove(@drop1and2, 1, 2)\\nequal(remove(compose(@temp1, 'a', 'b', 'c', 'd', 'e'), 1, 3), compose(@temp2, 'a', 'e')) == true\", 'copy, fill, inject, insert, prune');\n"
	"describe('#arrays', 'rsort',\t\"@array = rsort(@array)\",\t\t\t\t\t\t\t\"Sorts the elements of @array in descending order. The returned value is the input @array reference. To sort in ascending order, use sort(). If you need greater control over the sorting (e.g. how elements are compared), use the lower level function qsort() instead.\", \"rsort(@myArray)\\nequal(rsort(compose(@temp1, 1.1, -5, 1.5, 17, 0x10, 'xyz', 'a', 'def', 'a')), compose(@temp2, 'xyz', 'def', 'a', 'a', 17, 0x10, 1.5, 1.1, -5)) == true\", 'qsort, sort');\n"
	"describe('#arrays', 'qsort',\t\"qsort(+from, +to, >compare, >swap)\",\t\t\t\t\"This is an abstract implementation of the quicksort algorithm. qsort() handles the logic of the sorting algorithm (the bones) while you provide the functions >compare and >swap that carries out the concrete operations on the data being sorted (the meat).\\n\\n+from and +to defines the sorting range (+to is non-inclusive).\\n\\n>compare is called with two sorting indices and you should return a negative value if the data for the first index ($0) should be placed before the data for the second index ($1). Return a positive non-zero value for the opposite and return zero if the data is identical. (You can use the global ::compare function to easily implement this.)\\n\\n>swap is also called with two indices in $0 and $1 ($0 is always less than $1). The function should swap the data for the two indices. (You can use the global ::swap function to easily implement this.)\\n\\nThe functions sort() and rsort() use this function to implement sorting of entire arrays (ascending and descending respectively).  \", \"qsort(0, myArray.n, >myArray[$0] - myArray[$1], >swap(@myArray[$0], @myArray[$1]))\\nqsort(0, scrambleMe.n, >random(2) - 1, >swap(@scrambleMe[$0], @scrambleMe[$1]))\", 'compare, rsort, sort');\n"
	"describe('#arrays', 'sort',\t\t\"@array = sort(@array)\",\t\t\t\t\t\t\t\"Sorts the elements of @array in ascending order. The returned value is the input @array reference. To sort in descending order, use rsort(). If you need greater control over the sorting (e.g. how elements are compared), use the lower level function qsort() instead.\", \"sort(@myArray)\\nequal(sort(compose(@temp1, 1.1, -5, 1.5, 17, 0x10, 'xyz', 'a', 'def', 'a')), compose(@temp2, -5, 1.1, 1.5, 0x10, 17, 'a', 'a', 'def', 'xyz')) == true\", 'qsort, rsort');\n"
	"\n"
	"describe('#queues', 'resetQueue',\t\"resetQueue(@queue)\",\t\t\t\t\t\t\t\"Initializes the \\\"double-ended queue\\\" referenced to by @queue for use with pushBack(), popFront() etc by setting the sub-elements [@queue].m and [@queue].n to 0.\\n\\n[@queue].m is the index of the first element on the queue and it is decremented on pushFront() and incremented on popFront(). [@queue].n is one greater than the index of the last element on the queue and it is incremented on pushBack() and decremented on popBack(). (The 'm' and 'n' identifiers were chosen to make queue() compatible with some of the array functions such as append().)\", \"resetQueue(@dq)\", 'popBack, popFront, pushBack, pushFront, queueSize');\n"
	"describe('#queues', 'queueSize',\t\"+count = queueSize(@queue)\",\t\t\t\t\t\"Returns the count of elements in the double-ended queue @queue. The count is defined by [@queue].n - [@queue].m (see resetQueue() for an explanation). (@queue must have been initialized with resetQueue() prior to calling this routine.)\", \"count = queueSize(@dq)\", 'popBack, popFront, pushBack, pushFront, resetQueue');\n"
	"describe('#queues', 'popBack',\t\t\"<value> = popBack(@queue)\",\t\t\t\t\t\"Pops <value> from the back of the double-ended queue @queue. If @queue is empty an exception will be thrown. (@queue must have been initialized with resetQueue() prior to calling this routine.)\", \"lastIn = popBack(@dq)\", 'popFront, pushBack, pushFront, queueSize, resetQueue');\n"
	"describe('#queues', 'pushBack',\t\t\"@queue = pushBack(@queue, <value>)\",\t\t\t\"Pushes <value> to the back of the double-ended queue @queue. The returned value is the input @queue reference. (@queue must have been initialized with resetQueue() prior to calling this routine.)\\n\\nIt is also legal to call append() to push several elements at once to a queue.\", \"pushBack(@dq, 'lastIn')\", 'append, popBack, popFront, pushFront, queueSize, resetQueue');\n"
	"describe('#queues', 'popFront',\t\t\"<value> = popFront(@queue)\",\t\t\t\t\t\"Pops <value> from the front of the double-ended queue @queue. If @queue is empty an exception will be thrown. (@queue must have been initialized with resetQueue() prior to calling this routine.)\", \"firstOut = popFront(@dq)\", 'popBack, pushBack, pushFront, queueSize, resetQueue');\n"
	"describe('#queues', 'pushFront',\t\"@queue = pushFront(@queue, <value>)\",\t\t\t\"Pushes <value> to the front of the double-ended queue @queue. The returned value is the input @queue reference. (@queue must have been initialized with resetQueue() prior to calling this routine.)\", \"pushFront(@dq, 'firstOut')\", 'popBack, popFront, pushBack, queueSize, resetQueue');\n"
	"\n"
	"describe('#debug', 'assert',\t\"assert(?testResult|>testMe, ['description'])\",\t\t\"Asserts are used to check for programming errors in run-time. Until you run \\\"debug.pika\\\", asserts are disabled which means this function will do absolutely nothing (it is defined as an empty function in \\\"stdlib.pika\\\"). Running \\\"debug.pika\\\" will enable asserts by redefining this function. When enabled, it either checks the boolean ?testResult or executes >testMe and checks the result.\\n\\nTwo things differ depending on the choice of passing a boolean or a function / lambda expression. If you pass a boolean, e.g. assert(myfunc() == 3), and assertions are disabled, the argument will still be evaluated, i.e. myfunc() will still be called. Furthermore, if 'description' is omitted, the exception on an assertion failure will simply contain 'true' or 'false'. \\n\\nIf you pass a function / lambda expression, e.g. assert(>myfunc() == 3), the argument will only be evaluated if assertions are enabled and the exception will contain the full expression. In most cases you will want to use this variant.\", \"assert(>(0 <= $0 <= 100))\\nassert(alwaysCallMe(), 'alwaysCallMe() failed miserably')\");\n"
	"describe('#debug', 'trace',\t\t\"trace([>tracer], [+level = 2])\",\t\t\t\t\t\"Sets or resets the tracer function. The tracer function is called at various points in the PikaScript interpreter code. For example, you can use it for tracing caught exceptions, function calls and even implement debuggers and profilers.\\n\\n+level ranges from 0 (no tracing) to 21 (maximum tracing) and determines which events that will trigger a callback. The default trace level of 2 calls the trace function on each function entry and exit. Other useful levels are 1 for tracing caught errors and 3 to trace every interpreted statement. (Please see \\\"PikaScriptImpl.h\\\" for a complete listing of all levels.)\\n\\nThe >tracer function will be called with the following arguments:\\n\\n$0 = the source code being executed\\n$1 = the offset into the source code\\n$2 = whether $3 is an lvalue or an rvalue (lvalue = identifier, rvalue = actual value)\\n$3 = the result from the last operation\\n$4 = trace level\\n$5 = false for \\\"entry\\\", true for \\\"exit\\\" (e.g. function call entry / exit).\\n\\nCall trace() without arguments to stop all tracing.\", \"trace()\\ntrace(function { print((if ($5) '} ' else '{ ') # if (exists(@^$callee)) ^$callee else '????') })\");\n"
	"\n"
	"describe('#help', 'help',\t\t\"help('page'|'/search')\", \"Prints a help page or searches the help database for text. Function syntax is documented with the following conventions:\\n\\n- Arguments in [ ] brackets are optional and default values may be documented like this: [arg = value]\\n- Vertical bar | is used to separate alternatives\\n- ... means repeat 0 or more times\\n- \\\"Type classes\\\" can be identified as follows: ?boolean, +number, 'string', >function, @reference, <arbitrary>\\n\\nType help('#categories') for a list of valid categories. help('#pages') lists all available help pages. You can also search the entire help database for a string with help('/search')\", \"help('#categories')\\nhelp('#pages')\\nhelp('#utils')\\nhelp('args')\\nhelp('/delete')\");\n"
	"describe('#help', 'describe',\t\"describe('category', 'page', 'syntax', ['description'], ['examples'], ['seealso'])\", \"Adds a help page to the database.\", \"describe('#mine', 'countIf', '+count = countIf(@array, <value>)', 'Counts the number of items in @array that is equal to <value>.', \\\"n = countIf(@fruits, 'apple')\\\")\");\n"
	"\n"
	"describe('#math', 'abs',\t'+y = abs(+x)',\t\t\t\t'Returns the absolute value of +x.', \"abs(3.7) == 3.7\\nabs(-3.7) == 3.7\\nabs(-infinity) == +infinity\", 'sign');\n"
	"describe('#math', 'acos',\t'+y = acos(+x)',\t\t\t\"Returns the arccosine of +x (which should be in the range -1 to 1 or the result will be undefined). The returned value is in the range 0 to PI.\\n\\nInverse: cos().\", \"acos(0.0) == PI / 2\\nacos(0.73168886887382) == 0.75\\nacos(cos(0.6)) == 0.6\", 'asin, atan, cos');\n"
	"describe('#math', 'asin',\t'+y = asin(+x)',\t\t\t\"Returns the arcsine of +x (which should be in the range -1 to 1 or the result will be undefined). The returned value is in the range -PI / 2 to PI / 2.\\n\\nInverse: sin().\", \"asin(0.0) == 0.0\\nasin(0.69613523862736) == 0.77\\nasin(sin(0.5)) == 0.5\", 'acos, atan, sin');\n"
	"describe('#math', 'atan',\t'+y = atan(+x)',\t\t\t\"Returns the arctangent of +x. The returned value is in the range -PI / 2 to PI / 2.\\n\\nInverse: tan().\", \"atan(0.0) == 0.0\\natan(0.93159645994407) == 0.75\\natan(tan(0.5)) == 0.5\", 'acos, asin, atan2, tan');\n"
	"describe('#math', 'atan2',\t'+z = atan2(+y, +x)',\t\t'Returns the arctangent of +y/+x with proper handling of quadrants. The returned value is in the range -PI to PI.', \"atan2(0.0, 1.0) == 0.0\\natan2(1.0, 0.0) == PI / 2\\natan2(sin(0.5), cos(0.5)) == 0.5\", 'atan');\n"
	"describe('#math', 'cbrt',\t'+y = cbrt(+x)',\t\t\t\"Returns the cube root of +x.\\n\\nInverse: cube(+y).\", \"cbrt(0.0) == 0.0\\ncbrt(0.421875) == 0.75\\ncbrt(cube(-0.7)) == -0.7\", 'sqr');\n"
	"describe('#math', 'ceil',\t'+y = ceil(+x)',\t\t\t'Returns the ceiling of value +x. Ceil() rounds both positive and negative values upwards.', \"ceil(0.0) == 0.0\\nceil(-0.99999) == 0.0\\nceil(1000.00001) == 1001.0\", 'floor, round, trunc');\n"
	"describe('#math', 'cos',\t'+y = cos(+x)',\t\t\t\t\"Returns the cosine of +x. The returned value is in the range -1 to 1.\\n\\nInverse: acos().\", \"cos(0.0) == 1.0\\ncos(0.72273424781342) == 0.75\\ncos(acos(0.5)) == 0.5\", 'acos, sin, tan');\n"
	"describe('#math', 'cosh',\t'+y = cosh(+x)',\t\t\t'Returns the hyperbolic cosine of +x.', \"cosh(0.0) == 1.0\\ncosh(0.9624236501192069) == 1.5\", 'sinh, tanh');\n"
	"describe('#math', 'cube',\t'+y = cube(+x)',\t\t\t\"Returns the cube of +x.\\n\\nInverse: cbrt(+y).\", \"cube(0.0) == 0.0\\ncube(0.90856029641607) == 0.75\\ncube(cbrt(-0.7)) == -0.7\", 'cbrt, sqr');\n"
	"describe('#math', 'exp',\t'+y = exp(+x)',\t\t\t\t\"Returns the exponential of +x. I.e, the result is e to the power +x.\\n\\nInverse: log().\", \"exp(0.0) == 1.0\\nexp(1.0) == 2.718281828459\\nexp(-0.28768207245178) == 0.75\\nexp(log(0.6)) == 0.6\", 'log, log2, log10, pow');\n"
	"describe('#math', 'factorial',\t'+y = factorial(+x)',\t'Returns the factorial of value +x. +x should be an integer in the range of 1 to 170.', \"factorial(10) == 3628800\");\n"
	"describe('#math', 'floor',\t'+y = floor(+x)',\t\t\t'Returns the floor of value +x. Floor() rounds both positive and negative values downwards.', \"floor(0.0) == 0.0\\nfloor(-0.99999) == -1.0\\nfloor(1000.00001) == 1000.0\", 'ceil, round, trunc');\n"
	"describe('#math', 'log',\t'+y = log(+x)',\t\t\t\t\"Returns the natural logarithm of +x (i.e. the logarithm with base e). +x should be positive or the result will be undefined.\\n\\nInverse: exp().\", \"log(0.0) == -infinity\\nlog(1.0) == 0.0\\nlog(2.7182818284591) == 1.0\\nlog(exp(0.6)) == 0.6\", 'exp, log2, log10, logb, nroot, pow');\n"
	"describe('#math', 'log2',\t'+y = log2(+x)',\t\t\t\"Returns the base-2 logarithm of +x. +x should be positive or the result will be undefined.\\n\\nInverse: pow(2, +y).\", \"log2(0.0) == -infinity\\nlog2(1.0) == 0.0\\nlog2(65536.0) == 16.0\\nlog2(pow(2, 1.3)) == 1.3\", 'exp, log, log10, logb, nroot, pow');\n"
	"describe('#math', 'log10',\t'+y = log10(+x)',\t\t\t\"Returns the base-10 logarithm of +x. +x should be positive or the result will be undefined.\\n\\nInverse: pow(10, +y).\", \"log10(0.0) == -infinity\\nlog10(1.0) == 0.0\\nlog10(10000.0) == 4.0\\nlog10(pow(10, 0.6)) == 0.6\", 'exp, log, log2, logb, nroot, pow');\n"
	"describe('#math', 'logb',\t'+y = logb(+b, +x)',\t\t\"Returns the logarithm of +x with base +b. +x should be positive or the result will be undefined. Equivalent to log(+x) / log(+b).\\n\\nInverses: +x = pow(+b, +y), +b = nroot(+y, +x).\", \"logb(20, 1.0) == 0.0\\nlogb(20, 8000) == 3\", 'exp, log, log2, log10, nroot, pow');\n"
	"describe('#math', 'nroot',\t'+x = nroot(+y, +z)',\t\t\"Returns the nth (+y) root of +z.\\n\\nInverse: +z = pow(+x, +y).\", \"nroot(11, pow(17, 11)) == 17\", 'exp, log, log2, logb, log10, pow');\n"
	"describe('#math', 'pow',\t'+z = pow(+x, +y)',\t\t\t\"Returns +x raised to the power of +y.\\n\\nInverses: +y = log(+z) / log(+x) or logb(+x, +z), +x = pow(+z, 1.0 / +y) or nroot(+y, +z).\", \"pow(0.0, 0.0) == 1.0\\npow(10.0, 4.0) == 10000.0\\npow(10.0, log10(0.8)) == 0.8\\npow(pow(2.8, 9.8), 1.0 / 9.8) == 2.8\", 'exp, log, log2, logb, log10, nroot');\n"
	"describe('#math', 'random',\t'+y = random(+x)',\t\t\t'Returns a pseudo-random number between 0 and +x.', 'random(100.0)');\n"
	"describe('#math', 'round',\t'+y = round(+x)',\t\t\t'Rounds the value of +x to the nearest integer. If the decimal part of +x is exactly 0.5, the rounding will be upwards (e.g. -3.5 rounds to 3.0).', \"round(1.23456) == 1\\nround(-1.6789) == -2\\nround(3.5) == 4.0\\nround(-3.5) == -3.0\\nround(1000.499999) == 1000.0\", 'ceil, floor, trunc');\n"
	"describe('#math', 'sign',\t'+y = sign(+x)',\t\t\t\"Returns -1 if +x is negative, +1 if +x is positive or 0 if +x is zero.\", \"sign(0.0) == 0.0\\nsign(12.34) == 1\\nsign(-infinity) == -1\", 'abs');\n"
	"describe('#math', 'sin',\t'+y = sin(+x)',\t\t\t\t\"Returns the sine of +x. The returned value is in the range -1 to 1.\\n\\nInverse: asin().\", \"sin(0.0) == 0.0\\nsin(0.84806207898148) == 0.75\\nsin(asin(0.5)) == 0.5\", 'asin, cos, tan');\n"
	"describe('#math', 'sinh',\t'+y = sinh(+x)',\t\t\t'Returns the hyperbolic sine of +x.', \"sinh(0.0) == 0.0\\nsinh(0.61958958372348) == 0.66\", 'cosh, tanh');\n"
	"describe('#math', 'sqr',\t'+y = sqr(+x)',\t\t\t\t\"Returns the square of +x.\\n\\nInverse: sqrt(+y).\", \"sqr(0.0) == 0.0\\nsqr(0.86602540378444) == 0.75\\nsqr(sqrt(0.75)) == 0.75\", 'cube, sqrt');\n"
	"describe('#math', 'sqrt',\t'+y = sqrt(+x)',\t\t\t\"Returns the square root of +x. +x should be positive or the result will be undefined.\\n\\nInverse: sqr(+y).\", \"sqrt(0.0) == 0.0\\nsqrt(0.5625) == 0.75\\nsqrt(sqr(0.7)) == 0.7\", 'sqr');\n"
	"describe('#math', 'tan',\t'+y = tan(+x)',\t\t\t\t\"Returns the tangent of +x.\\n\\nInverse: atan(+y).\", \"tan(0.0) == 0.0\\ntan(0.603982978253) == 0.69\\ntan(atan(0.3)) == 0.3\", 'atan, cos, sin');\n"
	"describe('#math', 'tanh',\t'+y = tanh(+x)',\t\t\t'Returns the hyperbolic tangent of +x.', \"tanh(0.0) == 0.0\\ntanh(0.9729550745276566) == 0.75\", 'cosh, sinh');\n"
	"describe('#math', 'trunc',\t'+y = trunc(+x, [+n = 0])',\t'Truncates the value of +x leaving up to +n decimal places intact. If +n is omitted, all decimals are truncated. Truncation rounds positive values downwards and negative values upwards.', \"trunc(1.23456) == 1\\ntrunc(-1.23456) == -1\\ntrunc(1.23456, 2) == 1.23\\ntrunc(1.5, 10) == 1.5\", 'ceil, floor, precision, round');\n"
	"\n"
	"describe('#objects', 'construct',\t\t\"@object = construct(@object, >constructor, [<arguments>, ...])\",\t\t\"Constructs\", \"\", 'destruct, new, newLocal, this');\n"
	"describe('#objects', 'destruct',\t\t\"+count = destruct(@object)\",\t\t\t\t\t\t\t\t\t\t\t\"Destructs\", \"\", 'construct, delete, prune');\n"
	"describe('#objects', 'gc',\t\t\t\t\"+count = gc()\",\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Garbage collect.\", \"\", 'new, newLocal');\n"
	"describe('#objects', 'invokeMethod',\t\"<result> = invokeMethod(@object, 'method', @args, [+offset = 0], [+count])\",\t\"Like invoke() but for methods.\", \"\", 'invoke');\n"
	"describe('#objects', 'method',\t\t\t\"'method' = method()\",\t\t\t\t\t\t\t\t\t\t\t\t\t\"Method called.\", \"\", 'this');\n"
	"describe('#objects', 'new',\t\t\t\t\"@object = new(>constructor, [<arguments>, ...])\",\t\t\t\t\t\t\"Allocates and constructs.\", \"\", 'construct, gc, newLocal');\n"
	"describe('#objects', 'newLocal',\t\t\"@object = newLocal(>constructor, [<arguments>, ...])\",\t\t\t\t\t\"Allocates and constructs on local heap.\", \"\", 'construct, gc, new');\n"
	"describe('#objects', 'this',\t\t\t\"@object = this()\",\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Object called.\", \"\", 'method');\n"
	"\n"
	"describe('#strings', 'char',\t\t\"'character' = char(+code)\",\t\t\t\t\t\t\"Returns the character represented by +code as a string. +code is either an ASCII or Unicode value (depending on how PikaScript is configured). If +code is not a valid character code the exception 'Illegal character code: {code}' will be thrown.\\n\\nInverse: ordinal('character').\", \"char(65) === 'A'\\nchar(ordinal('\xe5')) === '\xe5'\", 'ordinal');\n"
	"describe('#strings', 'chop',\t\t\"'chopped' = chop('string', +count)\",\t\t\t\t\"Removes the last +count number of characters from 'string'. This function is equivalent to 'string'{:length('string') - +count}. If +count is zero or negative, the entire 'string' is returned. If +count is greater than the length of 'string', the empty string is returned. (There is no function for removing characters from the beginning of the string because you can easily use 'string'{+count:}.)\", \"chop('abcdefgh', 3) === 'abcde'\\nchop('abcdefgh', 42) === ''\", 'length, right, trim');\n"
	"describe('#strings', 'bake',\t\t\"'concrete' = bake('abstract', ['escape' = \\\"{\\\"], ['return' = \\\"}\\\"])\",\t\"Processes the 'abstract' string by interpreting any text bracketed by 'escape' and 'return' as PikaScript expressions and injecting the results from evaluating those expressions. The default brackets are '{' and '}'. The code is evaluated in the caller's frame. Thus you can inject local variables like this: '{myvar}'.\", \"bake('The result of 3+7 is {3+7}') === 'The result of 3+7 is 10'\\nbake('Welcome back {username}. It has been {days} days since your last visit.')\", 'evaluate');\n"
	"describe('#strings', 'escape',\t\t\"'escaped' = escape('raw')\",\t\t\t\t\t\t\"Depending on the contents of the source string 'raw' it is encoded either in single (') or double (\\\") quotes. If the string contains only printable ASCII chars (ASCII values between 32 and 126 inclusively) and no apostrophes ('), it is enclosed in single quotes with no further processing. Otherwise it is enclosed in double quotes (\\\") and any unprintable ASCII character, backslash (\\\\) or quotation mark (\\\") is encoded using C-style escape sequences (e.g. \\\"line1\\\\nline2\\\").\\n\\nYou can use unescape() to decode an escaped string.\", \"escape(\\\"trivial\\\") === \\\"'trivial'\\\"\\nescape(\\\"it's got an apostrophe\\\") === '\\\"it''s got an apostrophe\\\"'\\nescape(unescape('\\\"first line\\\\n\\\\xe2\\\\x00tail\\\"')) === '\\\"first line\\\\n\\\\xe2\\\\x00tail\\\"'\", 'unescape');\n"
	"describe('#strings', 'find',\t\t\"+offset = find('string', 'chars')\",\t\t\t\t\"Finds the first occurrence of any character of 'chars' in 'string' and returns the zero-based offset (i.e. 0 = first character). The search is case-sensitive. If no characters in 'chars' exist in 'string', the length of 'string' is returned. Use rfind() to find the last occurrence instead of the first. Use span() to find the first occurrence of any character not present in 'chars'. Use search() to find sub-strings instead of single characters.\", \"find('abcd', 'd') == 3\\nfind('abcdcba', 'dc') == 2\\nfind('nomatch', 'x') == 7\", 'mismatch, rfind, search, span');\n"
	"describe('#strings', 'length',\t\t\"+count = length('string')\",\t\t\t\t\t\t\"Returns the character count of 'string'.\", \"length('abcd') == 4\");\n"
	"describe('#strings', 'lower',\t\t\"'lowercase' = lower('string')\",\t\t\t\t\t\"Translates 'string' character by character to lower case. Notice that the standard implementation only works with characters having ASCII values between 32 and 126 inclusively.\", \"lower('aBcD') === 'abcd'\", 'upper');\n"
	"describe('#strings', 'mismatch',\t\"+offset = mismatch('first', 'second')\",\t\t\t\"Compares the 'first' and 'second' strings character by character and returns the zero-based offset of the first mismatch (e.g. 0 = first character). If the strings are identical in contents, the returned value is the length of the shortest string. As usual, the comparison is case sensitive.\", \"mismatch('abcd', 'abcd') == 4\\nmismatch('abc', 'abcd') == 3\\nmismatch('abCd', 'abcd') == 2\", 'find, search, span');\n"
	"describe('#strings', 'ordinal',\t\t\"+code = ordinal('character')\",\t\t\t\t\t\t\"Returns the ordinal (i.e. the character code) of the single character string 'character'. Depending on how PikaScript is configured, the character code is an ASCII or Unicode value. If 'character' cannot be converted to a character code the exception 'Value is not single character: {character}' will be thrown.\\n\\nInverse: char(+code).\", \"ordinal('A') == 65\\nordinal(char(211)) == 211\", 'char');\n"
	"describe('#strings', 'precision',\t\"'string' = precision(+value, +precision)\",\t\t\t\"Converts +value to a decimal number string (in scientific E notation if required). +precision is the maximum number of digits to include in the output. Scientific E notation (e.g. 1.3e+3) will be used if +precision is smaller than the number of digits required to express +value in decimal notation. The maximum number of characters returned is +precision plus 7 (for possible minus sign, decimal point and exponent).\", \"precision(12345, 3) === '1.23e+4'\\nprecision(9876, 8) === '9876'\\nprecision(9876.54321, 8) === '9876.5432'\\nprecision(-0.000000123456, 5) === '-1.2346e-7'\\nprecision(+infinity, 1) === '+infinity'\", \"radix, trunc\");\n"
	"describe('#strings', 'radix',\t\t\"'string' = radix(+value, +radix, [+minLength])\",\t\"Converts the integer +value to a string using a selectable radix between 2 (binary) and 16 (hexadecimal). If +minLength is specified and the string becomes shorter than this, it will be padded with leading zeroes. May throw 'Radix out of range: {radix}' or 'Minimum length out of range: {minLength}'.\", \"radix(0xaa, 2, 12) === '000010101010'\\nradix(3735928559, 16) === 'deadbeef'\\nradix(0x2710, 10) === 10000\", 'precision');\n"
	"describe('#strings', 'repeat',\t\t\"'repeated' = repeat('repeatme', +count)\",\t\t\t\"Concatenates 'repeatme' +count number of times.\", \"repeat(' ', 5) === '     '\\nrepeat('-#-', 10) === '-#--#--#--#--#--#--#--#--#--#-'\");\n"
	"describe('#strings', 'replace',\t\t\"'processed' = replace('source', 'what', 'with', [>findFunction = search], [+dropCount = length(what)], [>replaceFunction = >$1])\",\t\"Replaces all occurrences of 'what' with 'with' in the 'source' string.\\n\\nThe optional >findFunction allows you to modify how the function finds occurrences of 'what' and +dropCount determines how many characters are replaced on each occurrence. The default >findFunction is ::search (and +dropCount is the number of characters in 'what'), which means that 'what' represents a substring to substitute. If you want this function to substitute any occurrence of any character in 'what', you can let >findFunction be ::find and +dropCount be 1. Similarly, you may use ::span to substitute occurrences of all characters not present in 'what'.\\n\\nFinally, >replaceFunction lets you customize how substrings should be replaced. It will be called with two arguments, the source substring in $0 and 'with' in $1, and it is expected to return the replacement substring.\", \"replace('Barbazoo', 'zoo', 'bright') === 'Barbabright'\\nreplace('Barbalama', 'lm', 'p', find, 1) === 'Barbapapa'\\nreplace('Bqaxrbzzabypeillme', 'Bbarel', '', span, 1) === 'Barbabelle'\\nreplace('B03102020', '0123', 'abmr', find, 1, >$1{$0}) === 'Barbamama'\", \"bake, find, search, span\");\n"
	"describe('#strings', 'reverse',\t\t\"'backwards' = reverse('string')\",\t\t\t\t\t\"Returns 'string' reversed.\", \"reverse('stressed') === 'desserts'\");\n"
	"describe('#strings', 'rfind',\t\t\"+offset = rfind('string', 'chars')\",\t\t\t\t\"As find(), but finds the last occurrence of any character of 'chars' instead of the first. -1 is returned if no character was found (unlike find() which returns the length of 'string').\", \"rfind('abcd', 'd') == 3\\nrfind('abcdcba', 'dc') == 4\\nrfind('nomatch', 'xyz') == -1\", 'find, rsearch, rspan');\n"
	"describe('#strings', 'right',\t\t\"'ending' = right('string', +count)\",\t\t\t\t\"Returns the last +count number of characters from 'string'. This function is equivalent to 'string'{length('string') - +count:}. If +count is greater than the length of 'string', the entire 'string' is returned. If +count is zero or negative, the empty string is returned. (There is no \\\"left\\\" function because you can easily use 'string'{:+count}.)\", \"right('abcdefgh', 3) === 'fgh'\\nright('abcdefgh', 42) === 'abcdefgh'\", 'chop, length, trim');\n"
	"describe('#strings', 'rsearch',\t\t\"+offset = rsearch('string', 'substring')\",\t\t\t\"As search(), but finds the last occurrence of 'substring' in 'string' instead of the first. A negative value is returned if 'substring' was not found (unlike search() which returns the length of 'string').\", \"rsearch('abcdabcd', 'cd') == 6\\nrsearch('nomatch', 'xyz') == -3\", 'rfind, rspan, search');\n"
	"describe('#strings', 'rspan',\t\t\"+offset = rspan('string', 'chars')\",\t\t\t\t\"As span(), but finds the last occurrence of a character not present in 'chars' instead of the first. -1 is returned if the entire 'string' consists of characters in 'chars (unlike span() which returns the length of 'string').\", \"rspan('abcd', 'abc') == 3\\nrspan('abcdcba', 'ab') == 4\\nrspan('george bush', 'he bugs gore') == -1\", 'rfind, rsearch, span');\n"
	"describe('#strings', 'search',\t\t\"+offset = search('string', 'substring')\",\t\t\t\"Finds the first occurrence of 'substring' in 'string' and returns the zero-based offset (e.g. 0 = first character). The search is case-sensitive. If 'substring' does not exist in 'string', the length of 'string' is returned. Use rsearch() to find the last occurrence instead of the first. Use find() to find the first occurrence of any character in a set of characters instead of a sub-string.\", \"search('abcdabcd', 'cd') == 2\\nsearch('nomatch', 'x') == 7\", 'find, mismatch, rsearch, span');\n"
	"describe('#strings', 'span',\t\t\"+offset = span('string', 'chars')\",\t\t\t\t\"Finds the first occurrence of a character in 'string' that is not present in 'chars' and returns the zero-based offset (i.e. 0 = first character). The search is case-sensitive. If the entire 'string' consists of characters in 'chars', the length of 'string' is returned. Use rspan() to find the last occurrence instead of the first. Use find() to find the first occurrence of any character in 'chars'.\", \"span('abcd', 'abc') == 3\\nspan('abcdcba', 'ab') == 2\\nspan('george bush', 'he bugs gore') == 11\", 'find, mismatch, rspan, search');\n"
	"describe('#strings', 'tokenize',\t\"tokenize('source', >processor, ['delimiters' = \\\"\\\\n\\\"])\",\t\t\t\"Divides the 'source' string into tokens separated by any character in 'delimiters' (linefeed by default). For every extracted token, >processor is called, passing the token as the single argument $0 (not including the delimiter). The final delimiter at the end of the string is optional. For example, tokenize() can be useful for reading individual lines from a text file, parsing tab or comma-separated data and splitting sentences into separate words.\", \"tokenize(\\\"First line\\\\nSecond line\\\\nLast line\\\\n\\\", >append(@lines, $0))\\ntokenize('Eeny, meeny, miny, moe', >print(trim($0)), ',')\\ntokenize('Data is not information, information is not knowledge, knowledge is not understanding, understanding is not!wisdom.', >if ($0 !== '') append(@words, $0), \\\" \\\\t\\\\r\\\\n,.!?&\\\\\\\"/;:=-()[]{}\\\")\", \"parse, trim, wildmatch\");\n"
	"describe('#strings', 'trim',\t\t\"'trimmed' = trim('string', ['leading' = \\\" \\\\t\\\\r\\\\n\\\"], ['trailing' = \\\" \\\\t\\\\r\\\\n\\\"])\", \"Trims the source 'string' from leading and / or trailing characters of choice. The default characters are any white space character. If you pass void to 'leading' or 'trailing' you can prevent the routine from trimming leading respectively trailing characters.\", \"trim(\\\"  extractme\\\\t\\\") === 'extractme'\\ntrim(\\\"\\\\n    keep trailing spaces  \\\\n\\\", , void) === \\\"keep trailing spaces  \\\\n\\\"\\ntrim(\\\"--- keep me ---\\\", '-', '-') === ' keep me '\", \"replace\");\n"
	"describe('#strings', 'unescape',\t\"'raw' = unescape('escaped')\",\t\t\t\t\t\t\"Converts a string that is either enclosed in single (') or double (\\\") quotes. If the single (') quote is used, the string between the quotes is simply extracted \\\"as is\\\" with the exception of pairs of apostrophes ('') that are used to represent single apostrophes. If the string is enclosed in double quotes (\\\") it can use a subset of the C-style escape sequences. The supported sequences are: \\\\\\\\ \\\\\\\" \\\\' \\\\a \\\\b \\\\f \\\\n \\\\r \\\\t \\\\v \\\\xHH \\\\uHHHH \\\\<decimal>. If the string cannot be successfully converted an exception will be thrown.\\n\\nInverse: escape('raw').\", \"unescape(\\\"'trivial'\\\") == 'trivial'\\nunescape('\\\"it''s got an apostrophe\\\"') == \\\"it's got an apostrophe\\\"\\nunescape(escape(\\\"first line\\\\n\\\\xe2\\\\x00tail\\\")) == \\\"first line\\\\n\\\\xe2\\\\x00tail\\\"\", 'escape, evaluate');\n"
	"describe('#strings', 'upper',\t\t\"'uppercase' = upper('string')\",\t\t\t\t\t\"Translates 'string' character by character to upper case. Notice that the standard implementation only works with characters having ASCII values between 32 and 126 inclusively.\", \"upper('aBcD') === 'ABCD'\", 'lower');\n"
	"describe('#strings', 'wildfind',\t\"+offset|void = wildfind('source', 'pattern', +from, +to, @captureQueue)\",\t\"This is a low-level subroutine used by wildmatch() to match the full or partial 'pattern' in 'source' between the offsets +from and +to (inclusively). The returned value is either the offset where the first match was found or void if no match was found. @captureQueue should be initialized with resetQueue() prior to calling this routine. \\\"Captured ranges\\\" will be pushed to this \\\"queue\\\" as pairs of offsets and lengths. Pop these with popFront().\\n\\nSee the documentation for wildmatch() for a description of the pattern syntax and more.\", \"wildfind('abcdef', 'def', 0, 6, @c) == 3\\nwildfind('abcdef', '[def]', 0, 6, @c) == 5\\nwildfind('abcdef', '[def]*', 0, 6, @c) == 3\\nwildfind('abcdef', '[^def]', 4, 6, @c) == void\", \"popFront, resetQueue, wildmatch\");\n"
	"describe('#strings', 'wildmatch',\t\"?matched = wildmatch('source', 'pattern', [@captures, ...])\",\t\t\"Tries to match the 'source' string with 'pattern' (which may contain \\\"wild card\\\" patterns). true is returned if there is a match. You may also capture substrings from 'source' into the @captures variables. The pattern syntax is inspired by the \\\"glob\\\" standard (i.e. the syntax used for matching file names in most operating systems). However, a lot of additional features have been added, making the complexity of the syntax somewhere between glob and \\\"regular expressions\\\". It is easiest to describe with some examples:\\n\\n*           any string (including the empty string)\\n?           a single arbitrary character\\n~           an optional arbitrary character\\nsmurf       the string 'smurf' exactly (comparison is always case sensitive)\\n*smurf*     'smurf' anywhere in the source\\n????~~~~    between four and eight arbitrary characters\\n[a-zA-Z]    any single lower or upper case letter between 'a' and 'z'\\n[^a-zA-Z]   any single character that is not between 'a' and 'z' (case insensitive)\\n[*]         matches a single asterisk\\n[^]         a single ^ character only\\n[[]]        [ or ]\\n[]^]        ] or ^\\n[x-]        x or -\\n[0-9]*      a string consisting of zero or more digits\\n[0-9]????   exactly four digits\\n[0-9]?*     a string consisting of one or more digits\\n[0-9]??~~   between two and four digits\\n[0-9]?[]*   a single digit and then an arbitrary string\\n{*}smurf    captures everything before 'smurf' into the next @captures variable\\n\\nNotice that the * and ~ quantifiers are always non-greedy (i.e. they match as little as they possibly can). (This is a limitation of the current implementation, there are plans to let double ** mark a greedy match instead.) If you want to perform case insensitive matching for the entire pattern, use lower() or upper() on the source string. There is also a low-level routine called wildfind() if you need greater control over the matching.\", \"wildmatch('readme.txt', '*.txt')\\nwildmatch('myfile.with.extension', '{[^<>:\\\"/\\\\|?*]*}.{[^<>:\\\"/\\\\|?*.]*}', @filename, @extension) && filename === 'myfile.with' && extension === 'extension'\\nwildmatch(LF # \\\"skip line\\\\n\\\\n\\\\tmatch : me \\\\nthis:is the rest\\\" # LF, \\\"*\\\\n[ \\\\t]*{[^ \\\\t]?*}[ \\\\t]*:*{[^ \\\\t]?[]*}[ \\\\t]*\\\\n{*}\\\", @key, @value, @theRest) && key === 'match' && value === 'me'\", \"lower, tokenize, upper, wildfind\");\n"
	"\n"
	"describe('#utils', 'args',\t\t'args([@variables, ...])',\t\t\t\t\t\t\t'Assigns arguments to named variables. Pass a reference to a local variable for each argument your function expects. The caller of your function must pass exactly this number of arguments or an exception will be thrown.', 'args(@x, @y)', 'vargs');\n"
	"describe('#utils', 'classify',\t\"'class' = classify(<value>)\",\t\t\t\t\t\t\"Examines <value> and tries to determine what \\\"value class\\\" it belongs to:\\n\\n- 'void' (empty string)\\n- 'boolean' ('true' or 'false')\\n- 'number' (starts with a digit, '+' or '-' and is convertible to a number)\\n- 'reference' (starting with ':' and containing at least one more ':')\\n- 'function' (enclosed in '{ }' or begins with '>:' and contains one more ':')\\n- 'native' (enclosed in '< >')\\n- 'string' (if no other match)\\n\\nNotice that since there are no strict value types in PikaScript the result of this function should be considered a \\\"hint\\\" only of what type <value> is. For example, there is no guarantee that a value classified as a 'function' actually contains executable code.\", \"classify(void) === 'void'\\nclassify('false') === 'boolean'\\nclassify(123.456) === 'number'\\nclassify(@localvar) === 'reference'\\nclassify(function { }) === 'function'\\nclassify(>lambda) === 'function'\\nclassify('<print>') === 'native'\\nclassify('tumbleweed') === 'string'\");\n"
	"describe('#utils', 'coalesce',\t'<value> = coalesce(<values>|@variables, ...)',\t\t\"Returns the first <value> in the argument list that is non-void, or the contents of the first @variables that exists (whichever comes first). void is returned if everything else fails.\\n\\nA word of warning here, if a string value happens to look like a reference (e.g. '::') it will be interpreted as a such which may yield unexpected results. E.g. coalesce('::uhuh', 'oops') will not return 'oops' if a global variable named 'uhuh' exists.\", \"coalesce(@gimmeVoidIfNotDefined)\\ncoalesce(maybeVoid, perhapsThisAintVoid, 'nowIAmDefinitelyNotVoid')\", 'defaults, exists');\n"
	"describe('#utils', 'compare',\t'<diff> = compare(<a>, <b>)',\t\t\t\t\t\t'Returns 0 if <a> equals <b>, -1 if <a> is less than <b> and 1 if <a> is greater than <b>. This function is useful in sorting algorithms.', \"compare('abc', 'def') < 0\\ncompare('def', 'abc') > 0\\ncompare('abc', 'abc') == 0\", 'qsort, swap');\n"
	"describe('#utils', 'defaults',\t'defaults([@variable, <value>, ...])',\t\t\t\t'Assigns each <value> to each @variable if it does not exist. This function is useful for initializing global variables and optional function arguments.', \"defaults(@name, 'Smith')\\ndefaults(@first, 'a', @last, 'z')\", 'coalesce');\n"
	"describe('#utils', 'delete',\t\"?deleted = delete(@variable)\",\t\t\t\t\t\t\"Deletes the variable referenced to by @variable and returns true if the variable existed and was successfully deleted.\\n\\nNotice that this function can only delete a single variable at a time. This means only a single \\\"element\\\" in a \\\"container\\\" as well. Use prune() to delete an entire \\\"plain old data\\\" container and destruct() to delete an object.\", \"delete(@begone)\\ndelete(@hurray[1972])\", 'destruct, exists, prune');\n"
	"describe('#utils', 'evaluate',\t\"<result> = evaluate('code', [@frame])\",\t\t\t\"Evaluates 'code' and returns the result. You can decide which frame should execute the code by supplying a reference in @frame. Without @frame, code is executed in its own frame just as if you would call a function. Only the \\\"frame identifier\\\" of @frame is used.\\n\\nYou may for example pass @$ to execute in the current frame, or @^$ to execute in the caller's frame (the '$' is there to reference the correct frame even if it is a lambda expression), or @:: to execute in the global frame.\", \"evaluate('3 + 3') == 6\\nevaluate('x = random(1)', @x)\", 'bake, invoke, parse, run, sourceFor, toSource');\n"
	"describe('#utils', 'exists',\t\"?found = exists(@variable)\",\t\t\t\t\t\t\"Returns true if the variable referenced to by @variable is defined. Notice that this function does not \\\"fall back\\\" to the global frame if a local variable does not exist. Therefore you should always prefix the variable name with '::' if you want to check for the existance of a global variable or function.\", \"exists(@::aglobal)\\nexists(@users['magnus lidstrom'])\", 'coalesce, defaults, delete');\n"
	"describe('#utils', 'include',\t\"include('filePath')\",\t\t\t\t\t\t\t\t\"Runs a PikaScript source file as with run() but only if 'filePath' has not been \\\"included\\\" before. The function determines this by checking the existance of a global ::included[filePath]. It defines this global after completing execution the first time. (run() does not define or use this global.) Use include() with source files that defines library functions and constants, e.g. 'stdlib.pika'.\", \"include('stdlib.pika')\", 'run');\n"
	"describe('#utils', 'input',\t\t\"'answer' = input('question')\",\t\t\t\t\t\t\"Prints 'question' and returns a line read from the standard input stream (excluding any terminating line feed characters). May throw 'Unexpected end of input file' or 'Input file error'.\", \"name = input(\\\"What's your name? \\\")\", 'print');\n"
	"describe('#utils', 'invoke',\t\"<result> = invoke(['callee'], [>body], @args, [+offset = 0], [+count])\",\t\"Calls 'callee' (or >body) with the argument list @args. The difference between using 'callee' or >body is that the former should be a string with a function name, while the latter should be an actual function body. If both arguments are present, >body will be executed, but the called function's $callee variable will be set to 'callee'. For debugging purposes it is recommended that you use the 'callee' argument.\\n\\n+offset can be used to adjust the element index for the first argument. +count is the number of arguments. If it is omitted, [@args].n is used to determine the count.\\n\\nMay throw 'Too few array elements'.\", \"invoke('max', , @values)\\ninvoke('(callback)', $0, @$, 1, 4)\", \"evaluate, invokeMethod, run\");\n"
	"describe('#utils', 'load',\t\t\"'contents' = load('filePath')\",\t\t\t\t\t\"Loads a file from disk and returns it as a string. The standard implementation uses the file I/O of the standard C++ library, which takes care of line ending conversion etc. It can normally only handle ASCII text files. May throw 'Cannot open file for reading: {filePath}' or 'Error reading from file: {filePath}'.\", \"data = load('myfolder/myfile.txt')\", 'save');\n"
	"describe('#utils', 'max',\t\t'<m> = max(<x>, <y>, [<z>, ...])',\t\t\t\t\t'Returns the largest value of all the arguments.', \"max(5, 3, 7, 1, 4) == 7\\nmax('Sleepy', 'Grumpy', 'Happy', 'Bashful', 'Dopey', 'Sneezy', 'Doc') === 'Sneezy'\\nmax('Zero', '10', '5') === 'Zero'\", 'min');\n"
	"describe('#utils', 'min',\t\t'<m> = min(<x>, <y>, [<z>, ...])',\t\t\t\t\t'Returns the smallest value of all the arguments.', \"min(5, 3, 7, 1, 4) == 1\\nmin('Sleepy', 'Grumpy', 'Happy', 'Bashful', 'Dopey', 'Sneezy', 'Doc') === 'Bashful'\\nmin('Zero', '10', '5') === '5'\", 'max');\n"
	"describe('#utils', 'parse',\t\t\"+offset = parse('code', ?literal)\",\t\t\t\t\"Parses 'code' (without executing it) and returns the number of characters that was successfully parsed. 'code' is expected to start with a PikaScript expression or in case ?literal is true, a single literal (e.g. a number). If ?literal is false, the parsing ends when a semicolon or any unknown or unexpected character is encountered (including unbalanced parentheses etc). The resulting expression needs to be syntactically correct or an exception will be thrown.\\n\\nYou can use this function to extract PikaScript code (or constants) inlined in other text. You may then evaluate the result with evaluate() and continue processing after the extracted code. Pass true for ?literal in case you want to evaluate a single constant and prevent function calls, assignments etc to be performed. Valid literals are: 'void', 'false', 'true', numbers (incl. hex numbers and 'infinity' of any sign), escaped strings (with single or double quotes), natives (enclosed in '< >'), function or lambda definitions.\", \"parse('3+3', false) == 3\\nparse('3+3', true) == 1\\nparse('1 + 2 * 3 ; stop at semicolon', false) == 10\\nparse(' /* leading comment */ code_here /* skip */ /* trailing */ /* comments */ but stop here', false) == 74\\nparse('stop after space after stop', false) == 5\\nparse('x + x * 3 ) * 7 /* stop at unbalanced ) */', false) == 10\\nparse('+infinity', true) == 9\\nparse('\\\"stop after the \\\\\\\", but before\\\" this text', true) == 31\", 'escape, evaluate, run, tokenize');\n"
	"describe('#utils', 'print',\t\t\"print('textLine')\",\t\t\t\t\t\t\t\t\"Prints 'textLine' to the standard output, appending a newline character. (Sorry, but standard PikaScript provides no means for outputting text without the newline.)\", \"print('Hello world!')\", 'input');\n"
	"describe('#utils', 'run',\t\t\"<result> = run('filePath', [<args>, ...])\",\t\t\"Loads and executes a PikaScript source file. The code is executed in the \\\"closure\\\" of the global frame, which means that variable assignments etc work on globals. The code can still use temporary local variables with the $ prefix. The passed <args> are available in $1 and up. $0 will be 'filePath'. The returned value is the final result value of the executed code, just as it would be for a function call. The first line of the source code file may be a \\\"Unix shebang\\\" (in which case it is simply ignored). Use include() if you wish to avoid a file from running more than once.\", \"run('chess.pika')\\nhtmlCode = run('makeHTML.pika', 'Make This Text HTML')\", 'evaluate, include, invoke');\n"
	"describe('#utils', 'save',\t\t\"save('filePath', 'contents')\",\t\t\t\t\t\t\"Saves 'contents' to a file (replacing any existing file). The standard implementation uses the file I/O of the standard C++ library, which takes care of line ending conversion etc. It can normally only handle ASCII text files. May throw 'Cannot open file for writing: {filePath}' or 'Error writing to file: {filePath}'.\", \"save('myfolder/myfile.txt', 'No, sir, away! A papaya war is on!')\", 'load');\n"
	"describe('#utils', 'sourceFor', \"'code' = sourceFor(@variable|@container, ['prefix' = ''])\",\t\t\"*** WARNING, THIS FUNCTION IS SLIGHTLY BROKEN AND MAY BE REMOVED. USE AT OWN RISK! ***\\n\\nCreates source code for recalling the definition of @variable or @container (with all its sub-elements). The created code can be used with evaluate() to recall the definition in any given frame. For example: evaluate('code', @$) would recreate variables in the current local frame and evaluate('code', @::) would create them in the global frame.\\n\\nEach output line will be prefixed with 'prefix'.\", \"save('AllGlobals.pika', sourceFor(@::))\\nevaluate(sourceFor(@wildmatch)) == wildmatch\\nevaluate(sourceFor(@::globalToLocalPlease), @$)\\nprint(sourceFor(@myFunction, \\\"\\\\t\\\\t\\\"))\", \"dump, evaluate, toSource\");\n"
	"describe('#utils', 'system',\t\"+exitCode = system('command')\",\t\t\t\t\t\"Tries to execute 'command' through the operating system's command interpreter. +exitCode is the return value from the command interpreter (a value of 0 usually means no error). May throw 'Error executing system command: {command}'.\");\n"
	"describe('#utils', 'swap',\t\t\"swap(@a, @b)\",\t\t\t\t\t\t\t\t\t\t\"Swaps the contents of the variables referenced to by @a and @b. This function is useful in sorting algorithms.\", \"swap(@master, @slave)\", 'compare, qsort');\n"
	"describe('#utils', 'time',\t\t\"+secs = time()\",\t\t\t\t\t\t\t\t\t\"Returns the system clock as \\\"epoch time\\\", i.e. the number of seconds that has passed since a specific reference date (usually January 1 1970).\", \"elapsed = time() - lastcheck\");\n"
	"describe('#utils', 'throw',\t\t\"throw('error')\",\t\t\t\t\t\t\t\t\t\"Throws an exception. 'error' should describe the error in human readable form. Use try() to catch errors. (PikaScript exceptions are standard C++ exceptions. It is up to the host application how uncaught exceptions are handled.)\", \"throw('Does not compute')\", 'try');\n"
	"describe('#utils', 'toSource',\t\"'literal' = toSource(<value>)\",\t\t\t\t\t\"*** WARNING, THIS FUNCTION IS SLIGHTLY BROKEN AND MAY BE REMOVED. USE AT OWN RISK! ***\\n\\nReturns the source code literal for <value>. I.e. 'literal' is formatted so that calling evaluate('literal') would bring back the original <value>.\", \"toSource('string theory') === \\\"'string theory'\\\"\\ntoSource('') === 'void'\\ntoSource('{ /* get funcy */ }') === 'function { /* get funcy */ }'\\nevaluate(toSource(@reffy)) == @reffy\\nevaluate(toSource(>lambchop), @$) == (>lambchop)\", \"dump, evaluate, sourceFor\");\n"
	"describe('#utils', 'try',\t\t\"'exception' = try(>doThis)\",\t\t\t\t\t\t\"Executes >doThis, catching any thrown exceptions and returning the error string of the exception. If no exception was caught, void is returned. The returned value of >doThis is discarded. (Although PikaScript exceptions are standard C++ exceptions you can only catch PikaScript errors with this function.)\", \"error = try(>data = load(file))\\ntry(>1+1) === void\\ntry(>1+'a') === \\\"Invalid number: 'a'\\\"\\ntry(>throw('catchme')) === 'catchme'\", 'throw');\n"
	"describe('#utils', 'vargs',\t\t'vargs([@arguments, ...], , [@optionals, ...])',\t'As args() but you may define arguments that are optional. The caller of your function must pass all required arguments or an exception will be thrown. An exception will also be thrown if the caller passes more optional arguments than present in vargs(). An easy way to assign default values for optional arguments is with the default() function. Alternatively you may want to use coalesce().', 'vargs(@required1, @required2, , @optional1, @optional2)', 'args, coalesce, defaults');\n"
	"describe('#utils', 'VERSION',\t\"'v' = VERSION\",\t\t\t\t\t\t\t\t\t'VERSION is a global variable containing the PikaScript engine version as a human readable text string.');\n";

const char* BUILT_IN_INTERACTIVE =
	"#! /usr/local/bin/PikaCmd\n"
	"\n"
	"/*\n"
	"\tinteractive.pika v0.941\n"
	"\n"
	"\tPikaScript is released under the \"New Simplified BSD License\". http://www.opensource.org/licenses/bsd-license.php\n"
	"\t\n"
	"\tCopyright (c) 2009-2013, NuEdge Development / Magnus Lidstroem\n"
	"\tAll rights reserved.\n"
	"*/\n"
	"\n"
	"interact = function {\n"
	"\tHELP = '\n"
	"Enter expressions to evaluate them interactively line by line. E.g.:\n"
	"\n"
	"    3+3\n"
	"    print(''hello world'')\n"
	"    run(''chess.pika'')\n"
	"    \n"
	"You can evaluate a multi-line expression by ending the first line with an opening curly bracket (''{''). Finish the expression with a single closing curly bracket (''}''). E.g.:\n"
	"\n"
	"    f = function {\n"
	"        print(''hello world'');\n"
	"    }\n"
	"    \n"
	"The special global variable ''_'' holds the result of the last evaluated expression. E.g.:\n"
	"\n"
	"    25 * 25\n"
	"    sqrt(_)\n"
	"    _ == 25\n"
	"\t\n"
	"Special commands are:\n"
	"\n"
	"    ?                        this help\n"
	"    <page>?                  shows a page from the standard library help system (type ''help?'' for more info)\n"
	"    =                        displays the full definition of the last evaluated expression\n"
	"    <variable>=              displays the full definition of a variable / function / container \n"
	"    %                        re-run last executed PikaScript source file\n"
	"    %['']<path>[''] [args...]  runs a PikaScript source file (optionally with arguments)\n"
	"    !<command>               executes a command with the operating system''s command interpreter\n"
	"    exit                     exits\n"
	"';\n"
	"\t\n"
	"\targs(@prompt, @where);\n"
	"\t::_ = void;\n"
	"\toneLine = function { limitLength(singleLine($0), CONSOLE_COLS - 7) };\n"
	"\tshow = function {\n"
	"\t\targs(@var);\n"
	"\t\tmore(var # if (classify(var) === 'reference' && (s = sourceFor(var, ' ')) !== '')\n"
	"\t\t\t\t(LF # repeat('=', 8) # LF # s # repeat('=', 8)));\n"
	"\t\t( void )\n"
	"\t};\n"
	"\tfor (; {\n"
	"\t\tif ((s = input(prompt)) === 'exit') ( false )\n"
	"\t\telse {\n"
	"\t\t\t::__ = void;\n"
	"\t\t\ttryThis => (::__ = evaluate(s, where));\n"
	"\t\t\tprintThis = '----- ( {oneLine(toSource(::__))} )';\n"
	"\t\t\t\n"
	"\t\t\tif (s{0} === '!') tryThis => (::__ = system(s{1:}))\n"
	"\t\t\telse if (s{0} === '%') {\n"
	"\t\t\t\tif (s === '%' && !exists(@arglist.n)) {\n"
	"\t\t\t\t\ttryThis = void;\n"
	"\t\t\t\t\tprintThis = \"No PikaScript source executed yet.\"\n"
	"\t\t\t\t} else {\n"
	"\t\t\t\t\tif (s !== '%') {\n"
	"\t\t\t\t\t\tfor (prune(@arglist); s !== void; s = s{i:}) {\n"
	"\t\t\t\t\t\t\ts = s{1 + span(s{1:}, ' '):};\n"
	"\t\t\t\t\t\t\tif (s !== void) {\n"
	"\t\t\t\t\t\t\t\tappend(@arglist, if (s{0} === \"'\" || s{0} === '\"') s{1:(i = 1 + find(s{1:}, s{0})) - 1}\n"
	"\t\t\t\t\t\t\t\t\t\telse s{:i = find(s, ' ')});\n"
	"\t\t\t\t\t\t\t}\n"
	"\t\t\t\t\t\t};\n"
	"\t\t\t\t\t\tif (!wildmatch(arglist[0], '*.[^/:\\]*')) arglist[0] #= '.pika';\n"
	"\t\t\t\t\t};\n"
	"\t\t\t\t\tl = '';\n"
	"\t\t\t\t\titerate(@arglist, >l #= ' ' # escape($2));\n"
	"\t\t\t\t\tprint('----- Running' # l);\n"
	"\t\t\t\t\ttryThis => (::__ = invoke('run', , @arglist));\n"
	"\t\t\t\t}\n"
	"\t\t\t}\n"
	"\t\t\telse if (s === '=') { tryThis => show(::_); printThis = void }\n"
	"\t\t\telse if (s === '?') { tryThis => print(HELP); printThis = void }\n"
	"\t\t\telse if (right(s, 1) === '?') { tryThis => help(chop(s, 1)); printThis = void }\n"
	"\t\t\telse if (right(s, 1) === '=') { tryThis => show(@[where][chop(s, 1)]); printThis = void }\n"
	"\t\t\telse if (right(s, 1) === '{') {\n"
	"\t\t\t\tprint('(Multi-line input. Finish with a single ''}''.)');\n"
	"\t\t\t\tfor (; { s #= LF # (l = input('')); l !== '}' }; );\n"
	"\t\t\t};\n"
	"\n"
	"\t\t\tif (tryThis !== void && (x = try(tryThis)) !== void) printThis = '!!!!! {x}';\n"
	"\t\t\tif (printThis !== void) print(bake(printThis));\n"
	"\t\t\t::_ = ::__;\n"
	"\t\t\t( true )\n"
	"\t\t}\n"
	"\t}; );\n"
	"};\n"
	"\n"
	"if (exists(@$1) && $1 == 'go') {\n"
	"\tinclude('stdlib.pika');\n"
	"\tinclude('debug.pika');\n"
	"\tprint(\"Type '?' for help.\");\n"
	"\tinteract('Pika> ', @::);\n"
	"};\n";

const char* BUILT_IN_STDLIB =
	"/*\n"
	"\tstdlib.pika v0.941\n"
	"\n"
	"\tPikaScript is released under the \"New Simplified BSD License\". http://www.opensource.org/licenses/bsd-license.php\n"
	"\t\n"
	"\tCopyright (c) 2009-2013, NuEdge Development / Magnus Lidstroem\n"
	"\tAll rights reserved.\n"
	"*/\n"
	"\n"
	"// --- Utils ---\n"
	"\n"
	"args = function {\n"
	"\tif (^$n != $n) throw(if (^$n > $n) 'Too many arguments' else 'Too few arguments');\n"
	"\tfor (i = 0; i < $n; ++i) [$[i]] = ^$[i]\n"
	"};\n"
	"assert = function { };\n"
	"classifiers[''] = function { 'void' };\n"
	"classifiers['f'] = function { if ($0 === 'false') 'boolean' else 'string' };\n"
	"classifiers['t'] = function { if ($0 === 'true') 'boolean' else 'string' };\n"
	"classifiers['{'] = function { if ($0{length($0) - 1} === '}') 'function' else 'string' };\n"
	"classifiers['>'] = function { if ($0{1} === ':' && span(':', $0{2:}) == 1) 'function' else 'string' };\n"
	"classifiers[':'] = function { if (span(':', $0{1:}) == 1) 'reference' else 'string' };\n"
	"classifiers['<'] = function { if ($0{length($0) - 1} === '>') 'native' else 'string' };\n"
	"for ($i = 0; $i < 12; ++$i)\n"
	"\tclassifiers['0123456789+-'{$i}] = function { if (parse($0, true) == length($0)) 'number' else 'string' };\n"
	"classify = function { if (exists(p = @::classifiers[$0{0}])) [p]($0) else 'string' };\n"
	"coalesce = function {\n"
	"\tr = void;\n"
	"\tfor (i = 0; i < $n && ((r = $[i]) === void || classify(r) === 'reference' && if (!exists(r)) { r = void; true }\n"
	"\t\t\telse { r = [r]; false }); ++i);\n"
	"\t( r )\n"
	"};\n"
	"compare = function { if ($0 < $1) -1 else if ($0 > $1) 1 else 0 };\n"
	"defaults = function { for (i = 0; i + 2 <= $n; i += 2) if (!exists($[i])) [$[i]] = $[i + 1] };\n"
	"max = function { for (i = 1; i < $n; ++i) if ($[i] > $0) $0 = $[i]; ( $0 ) };\n"
	"min = function { for (i = 1; i < $n; ++i) if ($[i] < $0) $0 = $[i]; ( $0 ) };\n"
	"\n"
	"// FIX : sourceFor is outdated, we have new rules for dots etc in subscription\n"
	"sourceFor = function {\n"
	"\tvargs(@var, , @prefix);\n"
	"\tdefaults(@prefix, '');\n"
	"\ts0 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$';\n"
	"\tsX = s0 # '0123456789';\n"
	"\ttoSymbol => {\n"
	"\t\t// FIX : doesn't work with arrays :(, becomes a.3 instead of a[3] (I need to look at every first char after .)\n"
	"\t\tif (find(($0 = $0{1 + find($0{1:}, ':') + 1:}){0}, s0) == 0 && span($0{1:}, sX) >= length($0) - 1\n"
	"\t\t\t\t&& search($0, '..') >= length($0)) ( $0 )\n"
	"\t\telse ( '[' # escape($0) # ']' )\n"
	"\t};\n"
	"\tsrc = '';\n"
	"\t// FIX : can't really use toSource because of the ambiguity with function and strings like '{ alfons aaberg }' ...\n"
	"\tif (exists(var)) src #= prefix # toSymbol(var) # ' = ' # toSource([var]) # ';' # LF;\n"
	"\tforeach(var, >src #= prefix # toSymbol($0) # ' = ' # toSource($2) # ';' # LF);\n"
	"\t( src )\n"
	"};\n"
	"swap = function { t = [$0]; [$0] = [$1]; [$1] = t };\n"
	"\n"
	"// FIX : This function will describe any string looking like a function, e.g. '{ wrong!! }' as a function, even if it isn't.\n"
	"toSource = function {\n"
	"\tif ((c = classify($0)) === 'void') ( c )\n"
	"\telse if (c === 'string') ( escape($0) )\n"
	"\telse if (c === 'function') if ($0{0} !== '>') ( 'function ' # $0 ) else ( escape($0) )\n"
	"\telse if (c === 'reference') if ($0{0:2} === '::') ( '@' # $0 ) else ( escape($0) )\n"
	"\telse ( $0 )\n"
	"};\n"
	"vargs = function {\n"
	"\tfor (i = 0; i < $n && exists(@$[i]); ++i) {\n"
	"\t\tif (i >= ^$n) throw('Too few arguments');\n"
	"\t\tif (exists(@^$[i])) [$[i]] = ^$[i]\n"
	"\t};\n"
	"\tfor (++i; i < $n && i <= ^$n; ++i) if (exists(@^$[i - 1])) [$[i]] = ^$[i - 1];\n"
	"\tif (i <= ^$n) throw('Too many arguments');\n"
	"\t( i - 1 )\n"
	"};\n"
	"\n"
	"// --- Strings ---\n"
	"\n"
	"CR = \"\\r\";\n"
	"LF = \"\\n\";\n"
	"TAB = \"\\t\";\n"
	"WS = \" \\t\\r\\n\";\n"
	"bake = function {\n"
	"\topenLength = length(open = coalesce(@$1, '{'));\n"
	"\tcloseLength = length(close = coalesce(@$2, '}'));\n"
	"\tfor ({ out = ''; in = $0 }; in !== ''; ) {\n"
	"\t\tout #= in{:(i = search(in, open))};\n"
	"\t\tif ((in = in{i:}) !== '') {\n"
	"\t\t\ti = parse(in = in{openLength:}, false);\n"
	"\t\t\tout #= evaluate(in{:i}, @^$);\n"
	"\t\t\tif (in{i:closeLength} !== close) throw('Missing ' # escape(close));\n"
	"\t\t\tin = in{i + closeLength:};\n"
	"\t\t}\n"
	"\t};\n"
	"\t( out )\n"
	"};\n"
	"chop = function { $0{:length($0) - $1} };\n"
	"repeat = function { $1 *= length($0); for (s = $0; length(s) < $1;) s #= s; ( s{:$1} ) };\n"
	"replace = function {\n"
	"\tvargs(@src, @what, @with, , @findFunction, @dropCount, @replaceFunction);\n"
	"\tdefaults(@findFunction, search, @dropCount, length(what), @replaceFunction, >$1);\n"
	"\tif (dropCount <= 0) throw('Invalid drop count argument for replace()');\n"
	"\tfor (d = ''; { d #= src{:i = findFunction(src, what)}; i < length(src) }; src = src{i + dropCount:})\n"
	"\t\td #= replaceFunction(src{i:dropCount}, with);\n"
	"\t( d )\n"
	"};\n"
	"rfind = function { length($0) - 1 - find(reverse($0), $1) };\n"
	"right = function { $0{length($0) - $1:} };\n"
	"rspan = function { length($0) - 1 - span(reverse($0), $1) };\n"
	"rsearch = function { length($0) - length($1) - search(reverse($0), reverse($1)) };\n"
	"tokenize = function {\n"
	"\tvargs(@src, @func, , @delim);\n"
	"\tdefaults(@delim, LF);\n"
	"\tfor (; src !== ''; ) {\n"
	"\t\tfunc(src{:(i = find(src, delim))});\n"
	"\t\tsrc = src{i + 1:};\n"
	"\t};\n"
	"\t( void )\n"
	"};\n"
	"trim = function {\n"
	"\tvargs(@src, , @leading, @trailing);\n"
	"\tb = span(src, coalesce(@leading, WS));\n"
	"\te = rspan(src, coalesce(@trailing, WS));\n"
	"\t( src{b:e + 1 - b} )\n"
	"};\n"
	"unescape = function { if (span($0{0}, \"\\\"'\") != 1) throw('Invalid string literal'); ( evaluate($0) ) };\n"
	"\n"
	"// FIX : move to parsing.pika\n"
	"wildfind = function /* $0=string, $1=pattern, $2=from, $3=to, $4=captureQueue */ {\n"
	"\tif ((brk = find($1, '*?~[{}')) != 0) {\n"
	"\t\tfor ({ i = $2; $3 = min($3, length($0) - (l = length($1{:brk}))) }\n"
	"\t\t\t\t; (i += search($0{i:$3 + l - i}, $1{:brk})) <= $3 && wildfind($0, $1{brk:}, i + l, i + l, $4) === void\n"
	"\t\t\t\t; ++i)\n"
	"\t} else if ($1 === '') i = length($0)\n"
	"\telse if ((c = $1{0}) === '{' || c === '}') {\n"
	"\t\tif ((i = wildfind($0, $1{1:}, $2, $3, $4)) !== void)\n"
	"\t\t\tif (c === '{') { pushFront($4, popBack($4) - i); pushFront($4, i) } else pushBack($4, i)\n"
	"\t} else {\n"
	"\t\tset = '';\n"
	"\t\tif (c === '[') {\n"
	"\t\t\tif ($1{:2} === '[^' && $1{:3} !== '[^]' || $1{:4} === '[^]]') { findf = span; spanf = find; $1 = $1{2:} }\n"
	"\t\t\telse { findf = find; spanf = span; $1 = $1{1:} };\n"
	"\t\t\tfor (; $1 !== '' && $1{0} !== ']' || $1{:2} === ']]' || $1{:3} === ']^]'; $1 = $1{i:}) {\n"
	"\t\t\t\tset #= $1{:i = 1 + find($1{1:}, '-]')};\n"
	"\t\t\t\tif ($1{i} === '-' && $1{i + 1} !== ']') {\n"
	"\t\t\t\t\tfor ({ f = ordinal($1{i - 1}) + 1; t = ordinal($1{i + 1}) }; f <= t; ++f) set #= char(f);\n"
	"\t\t\t\t\ti += 2;\n"
	"\t\t\t\t}\n"
	"\t\t\t};\n"
	"\t\t\t$1 = $1{1:}\n"
	"\t\t};\n"
	"\t\tif (set === '') { findf => 0; spanf = length };\n"
	"\t\tmini = span($1, '?');\n"
	"\t\t$1 = $1{(maxi = mini + span($1{mini:}, '~')):};\n"
	"\t\tif (maxi == mini && $1{0} === '*') { maxi = 0x7FFFFFFF; $1 = $1{1:} }\n"
	"\t\telse if (mini == 0 && maxi == 0) mini = maxi = 1;\n"
	"\t\tif (mini == 0) findf => 0;\n"
	"\t\tfor (i = $2; (i += findf($0{i:$3 + 1 - i}, set)) <= $3 && ((n = spanf($0{i:maxi}, set)) < mini\n"
	"\t\t\t\t|| wildfind($0, $1, i + mini, i + n, $4) === void); i += max(n - mini, 0) + 1)\n"
	"\t};\n"
	"\t( if (i <= $3) i else void )\n"
	"};\n"
	"wildmatch = function {\n"
	"\tresetQueue(@cq);\n"
	"\tif (found = (wildfind($0, $1, 0, 0, @cq) == 0)) {\n"
	"\t\tfor (i = 2; i < $n; ++i) { offset = popFront(@cq); length = popFront(@cq); [$[i]] = $0{offset:length} }\n"
	"\t};\n"
	"\t( found )\n"
	"};\n"
	"\n"
	"// --- Math ---\n"
	"\n"
	"E = 2.71828182845904523536;\n"
	"PI = 3.14159265358979323846;\n"
	"cbrt = function { pow(abs($0), 1 / 3) * sign($0) };\n"
	"cube = function { $0 * $0 * $0 };\n"
	"factorial = function { if (~~$0 > 170) ( +infinity ) else { v = 1; for (i = 2; i <= $0; ++i) v *= i } };\n"
	"log2 = function { log($0) * 1.44269504088896340736 };\n"
	"logb = function { log($1) / log($0) };\n"
	"nroot = function { pow($1, 1 / $0) };\n"
	"round = function { floor($0 + 0.5) };\n"
	"sign = function { if ($0 < 0) -1 else if ($0 > 0) 1 else 0 };\n"
	"sqr = function { $0 * $0 };\n"
	"trunc = function {\n"
	"\tm = (if (exists(@$1)) pow(10, min(max(~~$1, 0), 23)) else 1);\n"
	"\t( (if ($0 < 0) ceil($0 * m) else floor($0 * m)) / m )\n"
	"};\n"
	"\n"
	"// --- Containers ---\n"
	"\n"
	"ascend = function { $0{:rfind($0, '.')} };\n"
	"clone = function { t = $1; foreach($0, >[t][$1] = $2); if (exists($0)) [t] = [$0]; ( $1 ) };\n"
	"map = function { for (i = 1; i + 2 <= $n; i += 2) [$0][$[i]] = $[i + 1]; ( $0 ) };\n"
	"prune = function { n = 0; foreach($0, >if (delete($0)) ++n); if (delete($0)) ++n; ( n ) };\n"
	"redotify = function { replace($0, '%', void, find, 3, >char(evaluate('0x' # $0{1:}))) };\n"
	"set = function { for (i = 1; i < $n; ++i) [$0][$[i]] = true; ( $0 ) };\n"
	"undotify = function { replace($0, '.%', void, find, 1, >'%' # radix(ordinal($0), 16, 2)) };\n"
	"\n"
	"// --- Arrays ---\n"
	"\n"
	"append = function { defaults(@[$0].n, 0); for (i = 1; i < $n; ++i) [$0][[$0].n++] = $[i]; ( $0 ) };\n"
	"compose = function { for (i = 1; i < $n; ++i) if (exists(@$[i])) [$0][i - 1] = $[i]; [$0].n = $n - 1; ( $0 ) };\n"
	"copy = function {\n"
	"\tif ($1 >= $4) for (i = 0; i < $2; ++i) [$3][$4 + i] = [$0][$1 + i]\n"
	"\telse for (i = $2 - 1; i >= 0; --i) [$3][$4 + i] = [$0][$1 + i];\n"
	"\t[$3].n = max(coalesce(@[$3].n, 0), $4 + $2);\n"
	"\t( $3 )\n"
	"};\n"
	"decompose = function { for (i = 1; i < $n; ++i) if (exists(@$[i])) [$[i]] = [$0][i - 1]; ( void ) };\n"
	"equal = function { ( [$0].n == [$1].n && { for (i = 0; i < [$0].n && [$1][i] == [$0][i];) ++i; } == [$0].n ) };\n"
	"fill = function { for (i = $1 + $2; --i >= $1;) [$0][i] = $3; [$0].n = max(coalesce(@[$0].n, 0), $1 + $2); ( $0 ) };\n"
	"inject = function {\n"
	"\tif ($4 < 0 || $4 > [$3].n) throw('Insertion index out of bounds');\n"
	"\t[$3].n += $2;\n"
	"\tfor (i = [$3].n - 1; i >= $4 + $2; --i) [$3][i] = [$3][i - $2];\n"
	"\tfor (; i >= $4; --i) [$3][i] = [$0][i - $4 + $1];\n"
	"\t( $3 )\n"
	"};\n"
	"insert = function { inject(@$, 2, $n - 2, $0, $1) };\n"
	"iterate = function {\n"
	"\tfor ({ i = coalesce(@[$0].m, 0); n = [$0].n }; i < n; ++i) if (exists(p = @[$0][i])) $1(p, i, [p]) else $1(p, i);\n"
	"\t( i )\n"
	"};\n"
	"qsort = function {\n"
	"\tfor (--$1; $0 + 1 < $1; $0 = $l) {\n"
	"\t\tfor ({ $l = $0; $h = $1; $m = ($l + $h) \\ 2 }; $l < $h; ) {\n"
	"\t\t\tfor (; $l <= $h && $2($l, $m) <= 0 && $2($h, $m) >= 0; { ++$l; --$h });\n"
	"\t\t\tfor (; $l <= $h && $2($h, $m) > 0; --$h);\n"
	"\t\t\tfor (; $l <= $h && $2($l, $m) < 0; ++$l);\n"
	"\t\t\tif ($m == $l || $m == $h) $m ^= $h ^ $l;\n"
	"\t\t\tif ($l < $h) $3($l, $h);\n"
	"\t\t};\n"
	"\t\tqsort($0, $l, $2, $3)\n"
	"\t};\n"
	"\tif ($0 < $1 && $2($0, $1) > 0) $3($0, $1)\n"
	"};\n"
	"remove = function {\n"
	"\tn = [$0].n;\n"
	"\t$2 = (if (exists(@$2)) max($2, 0) else 1) + min($1, 0);\n"
	"\t$1 = max($1, 0);\n"
	"\t[$0].n = $1 + max(n - $1 - $2, 0);\n"
	"\tfor (i = $1; i < [$0].n; ++i) [$0][i] = [$0][i + $2];\n"
	"\tfor (; i < n; ++i) delete(@[$0][i]);\n"
	"\t( $0 )\n"
	"};\n"
	"rsort = function { args(@a); qsort(0, [a].n, >-compare([a][$0], [a][$1]), >swap(@[a][$0], @[a][$1])); ( a ) };\n"
	"sort = function { args(@a); qsort(0, [a].n, >compare([a][$0], [a][$1]), >swap(@[a][$0], @[a][$1])); ( a ) };\n"
	"\n"
	"// --- Queues ---\n"
	"\n"
	"resetQueue = function { [$0].m = [$0].n = 0 };\n"
	"queueSize = function { [$0].n - [$0].m };\n"
	"popBack = function { if ([$0].n - [$0].m <= 0) throw('Queue underrun'); v = [r = @[$0][--[$0].n]]; delete(r); ( v ) };\n"
	"pushBack = function { [$0][[$0].n++] = $1; ( $0 ) };\n"
	"popFront = function { if ([$0].n - [$0].m <= 0) throw('Queue underrun'); v = [r = @[$0][[$0].m++]]; delete(r); ( v ) };\n"
	"pushFront = function { [$0][--[$0].m] = $1; ( $0 ) };\n"
	"\n"
	"// --- Objects ---\n"
	"\n"
	"_finddot = function { if ((i = rfind($0, '.')) < 0) throw('Non-method call'); ( i ) };\n"
	"construct = function { destruct($0); invoke($0 # '.construct', $1, @$, 2); ( $0 ) };\n"
	"destruct = function { if (exists(@[$0].destruct)) [$0].destruct(); ( prune($0) ) };\n"
	"gc = function {\n"
	"\tmark => {\n"
	"\t\tinclude = if ($1) >true else >{ (($t = $0{span($0, '0123456789')}) !== void && $t !== '.') };\n"
	"\t\tcheck => if ((include($1) && $2{0} === ':')\n"
	"\t\t\t\t&& (($c = span($2{($i = find($2{1:}, ':') + 2):}, '0123456789')) >= 1)\n"
	"\t\t\t\t&& (($t = $2{$i += $c}) === void || $t === '.')\n"
	"\t\t\t\t&& (!exists(@[($r = $2{:$i})].$_gc_marked))) { [$r].$_gc_marked = true; mark($r, true) };\n"
	"\t\tif (exists($0)) check($0, void, [$0]);\n"
	"\t\tforeach($0, check);\n"
	"\t};\n"
	"\tfor (frame = @^; { mark(frame, false); frame !== '::'; }; frame = @[frame # '^']);\n"
	"\tcount = 0;\n"
	"\tfor (frame = @^; {\n"
	"\t\t\tlast = void;\n"
	"\t\t\tforeach(frame, >if (last !== ($r = @[frame][$1{:($i = span($1, '0123456789'))}])\n"
	"\t\t\t\t\t\t&& (($t = $1{$i}) === void || $t === '.')) {\n"
	"\t\t\t\t\tif (!exists($m = @[(last = $r)].$_gc_marked)) { destruct($r); ++count };\n"
	"\t\t\t\t\tdelete($m)\n"
	"\t\t\t\t});\n"
	"\t\t\tframe !== '::'\n"
	"\t\t}; frame = @[frame # '^']);\n"
	"\t( count )\n"
	"};\n"
	"invokeMethod = function { defaults(@$3, 0, @$4, [$2].n - $3); invoke($0 # '.' # $1, [$0][$1], $2, $3, $4) };\n"
	"method = function { ^$callee{_finddot(^$callee) + 1:} };\n"
	"new = function { defaults(@::_alloc, 0); invoke(@::[x = ::_alloc++] # '.construct', $0, @$, 1); ( @::[x] ) };\n"
	"newLocal = function { defaults(@^_alloc, 0); invoke(@^[x = ^_alloc++] # '.construct', $0, @$, 1); ( @^[x] ) };\n"
	"this = function { if ((t = ^$callee{:_finddot(^$callee)}){0} === ':') ( t ) else ( @^^[t] ) };\n"
	"\n"
	"( void )\n";
